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);
}




3 comments:

sudhakar said...

in the server code
i'm getting below error

No overload for method 'GetField' takes '3' arguments

Unknown said...

The line:
sm.GetType().GetField("_isInAsyncPostBack", System.Reflection.BindingFlags.NonPublic System.Reflection.BindingFlags.Instance).SetValue(sm, true);
is missing a caret (^) inbetween 'NonPublic' and 'System'

Unknown said...

In addition to the last comment, where I think maybe using the pipe would be better |, there is an ampersand & missing at the top of the post in the following line:
var body = args.get_request().get_body() + 'X-MicrosoftAjax=' + encodeURIComponent('Delta=true');
The X-MicrosoftAjax needs to be prefixed with an ampersand & or else this fix will not work, but will also break things like ImageButtons.


So try using this instead (hopefully my stuff won't get stripped out):

In 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);
}