Search code examples
jqueryasp.netajaxhttphandleronunload

AJAX POST to handler on unload not working after 60 seconds in ASP.NET


In ASP.NET I'm using jQuery AJAX on the page unload to POST to an http handler. This works as expected--AJAX fires as the page unloads... unless I remain on the page for longer than 60 seconds. After that, when the page is closed, the AJAX POST does not appear to be hitting the server. It works fine on my localhost, but not in our development or qa environments.

Fiddler either shows nothing or gives me a generic 401 when the handler is called. I wrote up a simple test script to use AJAX to ping the server every 30 seconds in case we were getting some kind of timeout or the NTLM token was expiring, but no dice. We could see the ping on the server, but we can't see the AJAX POST on the server at all unless it's fired before the 60 seconds are up.

Here's the AJAX POST. It was originally just using jQuery.post(), but I wanted to try setting withCredentials to true to see if that was the issue (it didn't help).

jQuery(window).bind("unload.audit", function () {
    jQuery.ajax({
        type: "POST",
        url: "IndicativeDataAuditHandler.axd?HasUnsavedChanges=" + _hasUnsavedChanges() + "&PageTitle=" + document.title,
        xhrFields: { withCredentials: true }
    });
});

Here's the handler entry in the Web.config:

<add name="IndicativeDataAuditHandler" path="IndicativeDataAuditHandler.axd" 
     verb="POST, HEAD" type="Namespace.Namespace, App_Code" preCondition="integratedMode"/>

And here's (the important parts of) the handler code. It calls a CSLA object.

public class IndicativeDataAuditHandler : IHttpHandler, IRequiresSessionState
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        try
        {
            var applicationID = new Guid(ConfigurationManager.AppSettings["ApplicationID"]);
            var referrerUrl = context.Request.UrlReferrer.ToString();
            IndicativeDataAuditLogCommand.InsertAuditLog(applicationID, GetPageTitle(context), referrerUrl, GetHasUnsavedChanges(context), GetPartyID(context), GetUserID(context));
        }
        catch(Exception ex)
        {
            throw new Exception("Failed to send indicative data edit request log.", ex);
        }
    }
    //Some private methods here to get parameters
}

Any ideas or possible explanations as to why this might be happening?


Solution

  • The answer was turning off asynchronous requests for this AJAX POST, so it looks like this:

    jQuery.ajax({
        type: "POST",
        async: false,
        url: "IndicativeDataAuditHandler.axd?HasUnsavedChanges=" + _hasUnsavedChanges() + "&PageTitle=" + document.title,
        xhrFields: { withCredentials: true }
    });
    

    Due to this question and the fact that we were sometimes getting no request/response on the server side, I suspected that the AJAX call was not completing before the page closed.

    From what I understand, it's often a bad idea to turn async off, especially as the page is unloading, so take this with a grain of salt. We have determined this solution is acceptable for our intranet application.