Friday, October 26, 2007

Asp.net Ajax PageRequestManagerParserErrorException in Firefox


When using Ajax update panels we get the PageRequestManagerParserErrorException intermittently. This is due to the proxy which removes the "X-MicrosoftAjax" = "Delta=true" header from the XMLHttpRequest while sending the request randomly.


This was causing the Page to throw an alert with text:


Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write, response filters, HttpModules or server trace is enabled. Details: Error parsing near ''


After reading multiple posts, I could not find a solution to this problem except some places which mentioned that the proxy has to be removed. This is not an ideal solution as we could not ask all the users to remove the proxies.

So I came up with a hack which works till there is a better solution available:

This involves 2 steps in JS on the ClientSide and on the Server Side:

In the Javascript:


window.isFireFox = (navigator.userAgent.indexOf("Firefox") != -1);


if(window.isFireFox)
{
window.addEventListener('load',OnPageLoad,false);
function OnPageLoad()
{
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(OnBeginRequest);
}

function OnBeginRequest(sender, args)
{
var delta = args.get_request().get_headers()['X-MicrosoftAjax'];
if(delta == 'Delta=true')
{
var body = args.get_request().get_body() + 'X-MicrosoftAjax=' + encodeURIComponent('Delta=true');
args.get_request().set_body(body);
}
}
}




In the Page Init Complete:


protected override void OnInitComplete(EventArgs e)
{
#region Firefox Fix

ScriptManager sm = ScriptManager.GetCurrent(this);
if (IsPostBack && Request.Browser.Browser == "Firefox" && sm!=null && sm.IsInAsyncPostBack == false && Request.Form["X-MicrosoftAjax"] == "Delta=true")
{
sm.GetType().GetField("_isInAsyncPostBack", System.Reflection.BindingFlags.NonPublic System.Reflection.BindingFlags.Instance).SetValue(sm, true);
}
#endregion
base.OnInitComplete(e);
}