MS AJAX UpdatePanel throws Sys.WebForms.PageRequestManagerParserErrorException

I wrote ASP.NET code to call a service to generate and download a PDF file. At first, I tried to use AJAX UpdatePanel in the ASP.NET code to show progress because the service call may take long time. When the service call returned, I wanted to show the PDF file directly in browser on the same ASP.NET page:
  // Stream PDF kit to client
Byte[] buffer = File.ReadAllBytes(filePath);
base.Response.Clear();
base.Response.ContentType = "application/pdf";
int length = buffer.Length;
base.Response.AddHeader("Accept-Header", length.ToString());
base.Response.AddHeader("Content-Length", length.ToString());
base.Response.OutputStream.Write(buffer, 0, buffer.Length);
base.Response.Flush();
base.Response.End();

But I saw this exception message:

Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed ...

Then I realized the UpdatePanel JavaScript tried to parse the returned data for the original web page, but it received strange PDF stream instead. I found the explanation here:

The UpdatePanel control uses asynchronous postbacks to control which parts of the page get rendered. It does this using a whole bunch of JavaScript on the client and a whole bunch of C# on the server. Asynchronous postbacks are exactly the same as regular postbacks except for one important thing: the rendering. Asynchronous postbacks go through the same life cycles events as regular pages (this is a question I get asked often). Only at the render phase do things get different. We capture the rendering of only the UpdatePanels that we care about and send it down to the client using a special format. In addition, we send out some other pieces of information, such as the page title, hidden form values, the form action URL, and lists of scripts.

It turned out that I should using Response.Redirect() to another page to show the PDF file in browser. To avoid the same exception, there is no AJAX code in the second page.

8 comments:

Anonymous said...

Where to use Response.Redirect() assuming the code is

Byte[] buffer = File.ReadAllBytes(filePath);
base.Response.Clear(); base.Response.ContentType = "application/pdf";
int length = buffer.Length; base.Response.AddHeader("Accept-Header", length.ToString()); base.Response.AddHeader("Content-Length", length.ToString()); base.Response.OutputStream.Write(buffer, 0, buffer.Length); base.Response.Flush(); base.Response.End();

Can you tell me where to add Response.Redirect() nad how it will show download box to open pdf file

Jun Meng said...

The Response.Redirect() is called on the AJAX page. The PDF code should be moved to the second page without AJAX.

Or you can still use the first AJAX page, but put the "Generate PDF" button outside of UpdatePanel.

Zubin Girglani said...

There is no need to create a new page or move your control. All you have to do is specify that the button should perform a
synchronous postback (in the triggers section of the update panel).

Anonymous said...

Basically I want to use AsyanPostBackTrigger, because I am using ModalPopupExtender when process strat and stop. But It gives me parse error exception, as Response.xxx cant use in UpdatePanel.

Can you tell me how can I show ModalPopupExtender (or other grey effect) on page when process starts for generrating pdf and stops ModalPopupExtender when process ends.

Anonymous said...

@ Jun Meng
Thanks. that worked

Anonymous said...

Hey guys,

Thanks for the info. I found that if you add the button that executes the code to push the file (any kind) to the browser as a trigger:

'OpenTag'Triggers'CloseTag'
'OpenTag'asp:PostBackTrigger ControlID="btnYourButton" /'CloseTag'
'OpenTag'/Triggers'CloseTag'

Where open tag is a '<' and close tag is a '>'

All you're update panel problems are solved. (this is what zubirsinglani was trying to say)

Anonymous said...

Awesome, this is a great solution for AJAX Response.xxx issues.

Anonymous said...

This was worked for me.
http://chamilaw.blogspot.com/2011/04/syswebformspagerequestmanagerparsererro.html