Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
CheckActiveFormInSync showing wrong form
I am developing an application with several forms (with inheritance) containing several Frames (with inheritance). On the forms (and sometimes on a frame) I have buttons which should open the next form. Simply by filling some data in the next form and then using the .show of that next form. The same way I use buttons on a "deeper" form to return to the previous one by doing a callback to the previous form to transfer the data (with my own OnFinished procedure) and then close the form with a .hide. Most of the times that works fine. 

Sometimes however I need to click again after the first click on the open/close button. That would not be a big problem if not all the data I entered in edit fields was removed. After the first click, I found out, the current form (which I'm trying to leave) is fully rebuilt because of something called "CheckActiveFormInSync".

I tried to simpify the problem in a demo without the hassle of the inheritance and data transfer to and from the form. I think I found behaviour that very much resembles my problem. I think it has the same basis. 

I have a demo which creates two forms (in the demo I have a frame as well; it has the same problem as the form). From the first form I open the second form by clicking the button. The second form has a memo with an async KeyUpEvent doiing effectively nothing (but it is called). When I do nothing in the second form and press F5 te refresh, the second form is shown again (as expected). When I enter one or more characters in the memo (thus calling the async event) and then press F5, I am suddenly back in Form1, I think because of CheckActiveFormInSync.... It is in the calling stack of the OnOpen event of Form1. When I remove the async event from the memo an F5 does what it should do; refresh form 2

Delphi 10.3 with update 2
Intraweb 15.1.20

Attached Files
.zip (Size: 61.64 KB / Downloads: 1)
I tested your application and I believe that IW is doing the right thing here...

There is no simple answer for that scenario, but IW has several features to allow you to deal with it properly. There is one property in ServerController which is in play here:

- SecurityOptions.PreventDoubleSubmission (default True, set to True in your project)

This is the sequence of events in both cases:

a) 1st case - the one you consider "correct":

- Form1 is active. There is a POST request (let's call it request 1)
- Form2 becomes active.
- F5 is pressed -> The browser sends the POST request (2) again with the same parameters

Because of property PreventDoubleSubmission, IW detects that this is a refresh (request 1 and 2 are identical) and skips the request completely. It basically ignores the request and that's why your browser doesn't change (i.e. apparently on the browser, Form2 is still the active form)

b) 2nd case - the one you consider "incorrect":

- Form1 is active. There is a POST request (let's call it request 1)
- Form2 becomes active
- You press any key inside the memo (here we have another request 2)
- F5 is pressed -> The browser sends the POST request (3) which is exactly the same as request (1). Now, IW won't recognize this as a refresh because request 3 is not the same as previous request 2.
IW also detects that request 3 actually refers to Form1 (because it it the same as request 1) but your active form is Form2. In that case it makes Form1 the active form and processes the request as expected.

IMO, both cases are "correct".

If you disable PreventDoubleSubmission, case (a) and case (b) above should behave the same. But then you loose this feature (which I consider good to keep).

The other way of dealing with it (recommended) is enabling another IW feature which is controlled by ServerController.PostRedirectGet (Default disabled, set to disabled in your project).

You can read about it here:

Basically PostRedirectGet will generate a GET request after a POST request. So, when you press F5 the browser won't submit the same POST request again, but the GET request which doesn't do anything other than refreshing the page (without changing the content of the controls).

If you expect your users to press F5 and you have POST requests like that (e.g. IWButton.OnClick events) I strongly recommend you to turn on the PostRedirectGet feature.

There is another "manual" alternative which is using the OnBackButton event (in ServerController). That event will be triggered everytime that a second submit happens (F5 will trigger it). Using it you can manually control what IW does (e.g. SetActiveForm, ExecuteForm, etc).
- SetActiveForm True means that IW will try to set the active form of the application to match the one in the request (it might be different from the one the user sees)
- ExecuteForm True means that IW will go on and process the current active form

Using the PostRedirectGet will avoid all this trouble.

Please let me know if it works for you
Hi Alexandre,

Thanks for your fast and complete answer! I tested your advice with the demo application and it works fine. In my other application however it does not solve any problem and I am still running into unwanted CheckActiveFormInSync. I will try to build a new and better demo.

Forum Jump:

Users browsing this thread: 1 Guest(s)