1

I'm trying to catch when a user leaves a page (content page inside a master page) so I can update a flag in a database (the database isn't visible to the client PC so I can't code a link to it client side).

Currently I can catch the page unload with jQuery firing the __doPostBack() event, which I then catch server side.

However, this then stops the redirect from firing unless I code it as part of the code behind for the postback. As there are two buttons that are triggering this postback event that require different behaviour, this is causing a problem.

I've tried setting a viewstate to determine if the pageunload is caused by one of the two buttons, and stepping through the code I can see the button code fire correctly and updates the viewstate to the correct value, but when this then triggers the PageUnload code, the viewstate reverts to the previous value.

I've tried a hidden field, but the page isn't rebuilt before unloading the page so the hidden field still holds the previous value.

I've tried a page variable but again the value doesn't hold.

Is there a way to tell the code behind to continue with the redirect, or to set a flag that will help me trigger the correct redirect?

Current code: (on content page)

$(document).ready(function(){
$(window).unload(function(){
__doPostBack('Unload','');
});
});

(on page.load, code behind)

Dim eventtarget as String
Me.ClientScript.GetPostBackEventReference(Me, String.Empty)
If (Me.Request("__EVENTTARGET") is nothing) then
eventtarget = string.empty
else
eventtarget = Me.Request("__EVENTTARGET")
End If

If eventtarget = "Unload" then
closepage()
End If

closepage() just fires off the code I need to execute (record the page has been closed in the database).

Thanks.

2 Answers2

0

You could use an HTTP Handler to do the job, especially useful if lots of different pages have the same requirement..

$(document).ready(function(){
$(window).unload(function(){
            var xmlhttp;
            if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            }
            else {// code for IE6, IE5
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.open("GET", "http://yourPageClosedHandler.ashx?pageID=yourpageid", false);
            xmlhttp.send();
});
});

And then an http handler with this sort of code..

<%@ WebHandler Language="VB" Class="pageClosedHandler" %>

Imports System
Imports System.Web

    Public Class pageClosedHandler : Implements IHttpHandler

        Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            If Not IsNothing(context.Request.QueryString("pageID")) Then
                Dim pageID As String = context.Request.QueryString("pageID")
                ' do your stuff here
            End If
        End Sub

        Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Get
                Return False
            End Get
        End Property

    End Class

It would very exploitable though without more work so I wouldn't recommend it for a scenario where you need to know for sure the handler was invoked by your application.

trucker_jim
  • 572
  • 3
  • 7
  • Thanks for the reply. Security is an issue, and I only need to handle this on one page (thankfully). I'm currently looking at trapping the called URL (not having much success there, of cause), and moving the handling to the pre-unload stage to see if that is better. – user3729257 Jun 17 '14 at 07:30
  • You can trap the called URL via HttpContext.Current.Request.Url.AbsoluteUri if that helps.. – trucker_jim Jun 17 '14 at 07:48
  • I was looking at the HttpContext options - hadn't tried the .Request part, though, but found something else that seems to be doing the trick (posting the new code below) – user3729257 Jun 17 '14 at 14:00
0

Got a hint from another question on jQuery that seems to do the trick.

var leaving = true;

$(function(){
 $('a[rel=ext]').click(function(){leaving=false});
 $('form').submit(function() {leaving=false});
});

$(document).ready(function(){
 $(window).unload(function(){
  if(leaving){
   __doPostBack('Unload','');
  };
 });
});

This solves the one problem of the doPostBack firing when opening a new window (response.write).

The second problem was with a Response.Redirect - just added the ',true' to the end to stop further code executing (which is fine - everything that needed to execute had already been executed at that point.

Just got to test, test and test then pass to the testers to see if I missed anything.

  • You could use an ajax call to call a seperate logging page or httphandler. The page or handler could be called spuriously though...depends on the risks: http://stackoverflow.com/questions/9713058/sending-post-data-with-a-xmlhttprequest – trucker_jim Jun 18 '14 at 07:44