Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Response.End() generates an error when exporting gridview to excel file

I have this code:

protected void ibtGenerateReport_Click(object sender, ImageClickEventArgs e)
{
    string filename = "report.xls";             

    StringWriter stringWriter = new StringWriter();
    HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWriter);
    DataGrid DataGrd = new DataGrid();            
    DataGrd.DataSource = odsLSRAudit;
    DataGrd.DataBind();

    DataGrd.RenderControl(htmlWrite);            

    System.IO.StreamWriter vw = new System.IO.StreamWriter(filename, true);
    stringWriter.ToString().Normalize();
    vw.Write(stringWriter.ToString());
    vw.Flush();
    vw.Close();
    WriteAttachment(filename, "application/vnd.ms-excel", stringWriter.ToString());           
}

public static void WriteAttachment(string FileName, string FileType, string content)
{
    HttpResponse Response = System.Web.HttpContext.Current.Response;
    Response.ClearHeaders();
    Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
    Response.ContentType = FileType;
    Response.Write(content);            
    Response.End();
}

But the Response.End() gives me the below error:

Microsoft JScript runtime error: 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 '<table cellspacing="'.

The Response.Write(content) has the correct information as I can see. But no Save/Open dialog box appear, besides the above error.

I'm using UpdatePanels.

like image 527
Somebody Avatar asked Feb 18 '13 17:02

Somebody


2 Answers

Add this to your Page_Load() method

Assuming ibtGenerateReport is your button

protected void Page_Load(object sender, EventArgs e) {
   ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
   scriptManager.RegisterPostBackControl(this.ibtGenerateReport);
   //Further code goes here....
}

Explanation:

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. This is rendered out using a special format that the JavaScript on the client can understand. If you mess with the format by rendering things outside of the render phase of the page, the format will be messed up.

Why do I keeping getting a PageRequestManagerParserErrorException?

Well, chances are you're doing one of the things mentioned in the error message. Here are the most common reasons and why they don't work:

Calls to Response.Write(): By calling Response.Write() directly you are bypassing the normal rendering mechanism of ASP.NET controls. The bits you write are going straight out to the client without further processing.

Response filters /HttpModules : Similar to Response.Write(), they can change the rendering in such a way that the UpdatePanel won't know.

Server trace is enabled: Trace is effectively written out using Response.Write(), and as such messes up the special format that we use for UpdatePanel.

Calls to Server.Transfer(): Unfortunately, there's no way to detect that Server.Transfer() was called. This means that UpdatePanel can't do anything intelligent when someone calls Server.Transfer(). The response sent back to the client is the HTML markup from the page to which you transferred. Since its HTML and not the special format, it can't be parsed, and you get the error.

Solution: One way to avoid the parse error is to do a regular postback instead of an asynchronous postback by calling ScriptManager.RegisterPostBackControl()

Please refer to the complete Explanation and other solutions from Ellon Lipton's blog here

like image 177
feco Avatar answered Nov 14 '22 21:11

feco


Change Response.End by this:

Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();

Response.End is a bad practice, it aborts the thread to bypass the rest of the operations in the http request lifecycle and it throws an exception.

like image 4
Carlos Grappa Avatar answered Nov 14 '22 22:11

Carlos Grappa