From time to time I receive questions of IntraWeb users asking how they can terminate an user session and avoid that unused sessions continue to pile up in the server, consuming memory and resources.
It’s important to clarify that IntraWeb has a thread that runs in the background – at 1 minute intervals – and does the clean up of all unused sessions, after the session timeout period has elapsed. It means that, for example, if the session timeout is set to 20 minutes, between 20 and 21 minutes after the last user interaction (or more precisely the last request received by this session) the clean up thread will destroy this session and everything owned by it – i.e. all forms and the UserSession DataModule.
In general, there is no need to worry about this, unless you have a very long session timeout, or a very busy server where you may have thousands of simultaneous users. There are different strategies that can be used to limit the number of unused sessions:
1- Encourage your users to explicitly terminate your application, using a logout button or link. When the user executes the logout process the application can redirect the user to another site or even to a static page, calling WebApplication.TerminateAndRedirect() method. Please notice that when redirecting to a static page served by the same IntraWeb application, this must be in such a way that it won’t start another session – which would effectively make the whole logout process kind of useless. This can be done using a static HTML page or even better, a content handler that can provide dynamic content.
2- Use a short session timeout in conjunction with IWForm’s KeepAlive property. When set to True, IWForm.KeepAlive property generates code that pings the server and will effectively prevent the session from terminating due to a timeout. The KeepAlive property must be set in every application form where you don’t want the session to expire. The advantage compared to other user coded alternatives (e.g. a IWTimer) is that the KeepAlive request is very lightweight, does not lock the session, and is very fast. Having said that, do not use a IWTimer for this purpose. The only potential issue here is that the session won’t expire, as long as the user keeps the page active on the browser side, regardless if there is user interaction with the page. Some people – myself included – keep many pages open on their browser for days!
3- Starting with IntraWeb 15.2.69 released today, there is a new way to control the duration of the session. We have introduced a new IWForm event named OnAsyncPageUnloaded.
This event fires whenever the application user closes the browser tab where the application runs, or closes the browser itself. Please notice that it won’t trigger when the application switches to another form – even though the page effectively unloads. The purpose here is to detect when the user is leaving the application. Here is a code snippet used in the PageUnloadedDemo that we published on Github:
The Async event handler has 2 parameters as shown above: EventParams, the usual string list that contains all the request parameters and the AIsCurrent parameter. AIsCurrent indicates if the browser tab being closed is the one that the user is currently using. This may seem confusing but imagine the following scenario:
The application user opens your application and is interacting with it as usual. At some point, the user copies the application URL and pastes it into a new browser tab. If your application is not configured to run multiple sessions per user (via SeverController.SessionOptions.UniqueURL property), the user will effectively run the same session in 2 different browser tabs. One of them (the last one to be updated) is the current. The previous tab contains a copy (which may be outdated).
Back to the code snippet, the code inside the event handler tests if there is only one active form and calls a new WebApplication method, named SelfDestruct. This is the method signature:
This method will destroy a session if no other request is received after a minimum aSecs interval, in seconds as the name suggests. The exact point in time when the session will be effectively destroyed depends on the execution of the clean up thread. So, in practice, the session will be destroyed between aSecs and aSecs + 1 minute. In case the session receives a new request after calling SelfDestruct(), the self-destruct sequence will be aborted.
Please notice that the usage of WebApplication.Terminate() inside the OnAsyncPageUnloaded() event handler may not work as you expect in some cases especially if you are switching to another form using some redirection. That’s why WebApplication.SelfDestruct() is the correct way to terminate the session inside that event.
Personally, I would use all the 3 IntraWeb features described above to give the IntraWeb application user the best possible experience.