0

I'm having a problem with the conversion to Excel code I'm finding. I am working on a website project in .NET 4.0, and I have created a class for this that does the following (based on http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html):

HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition",
string.Format("attachment; filename={0}", fileName)); HttpContext.Current.Response.ContentType = "application/ms-excel"; using (StringWriter sw = new StringWriter()) {
   using (HtmlTextWriter htw = new HtmlTextWriter(sw)) {
    //Create a table to contain the grid
    //Add header row
    //Add each data row
    //Add Footer row
    //Render the table into the htmlwriter
    //  render the htmlwriter into the response
    HttpContext.Current.Response.Write(sw.ToString());
    HttpContext.Current.Response.End();
  }
}

I call this class from a usercontrol that contains a button that is added to a GridView displayed on the page. This works as expected - click the button, you are presented with a download option to either open or save the resulting excel spreadsheet containing the data from the GridView.

However, when I call this from a linkbutton inside a different GridView, I'd like to build a dynamic gridview to contain data and export that. When I do that, I get a ThreadAbortException from the Response.End call in the class.

Question 1: Why do I not get that ThreadAbortException when calling the same code from within a usercontrol? Do usercontrols get their own threads or some other kind of context?

Searching on the error I get when that ThreadAbortException occurs led me to attempt to replace it with ApplicationInstance.CompleteRequest(). When I do that I no longer get the ThreadAbortException, but this breaks the previously working usercontrol - instead of the resulting excel spreadsheet containing the data from the grid, it contains the HTML from the containing page, and at any rate it's easy enough to suppress that error with an empty catch. However, it doesn't fix the direct call with the dynamically generated GridView, that code renders a javascript error: "The message received from the server could not be parsed."

I would love to understand what exactly is going on here, but I'm at the point of needing results regardless of understanding. All the other approaches I've tried (datagrid instead of GridView, etc) run into the same problems, and are essentially the same when it comes down to "taking over" the current response and using stringwriter and htmlwriter to render the data into a response with excel contentType. And since this demonstrably works in the context of a usercontrol, I am at my wit's end as to why it won't work when called directly...

leppie
  • 115,091
  • 17
  • 196
  • 297
Jarrod
  • 1,535
  • 3
  • 16
  • 19
  • possible duplicate of [Why is my asp.net application throwing ThreadAbortException?](http://stackoverflow.com/questions/12476/why-is-my-asp-net-application-throwing-threadabortexception) – marc_s Jun 18 '11 at 06:17
  • I don't believe this is a duplicate - this is a very specific case dealing with two scenarios - one where it happens for a call to response.end, and the other it doesnt – Adam Tuliper Jun 18 '11 at 06:20

4 Answers4

1

The problem was actually completely unrelated to the excel export. The “…could not be parsed” error was the key. From these links I got the key, which was that the grid events cause only a partial postback event:

http://forums.asp.net/t/1392827.aspx

http://forums.aspfree.com/net-development-11/gridview-footer-template-button-in-updatepanel-not-posting-back-236087.html

This explains the ThreadAbortException and the “…could not be parsed” error. Adding this to the OnPreRender of the ImageButton was the solution:

protected void addTrigger_PreRender(object sender, EventArgs e)
{
    if (sender is ImageButton)
    {
        ImageButton imgBtn = (ImageButton)sender;
        ScriptManager ScriptMgr = (ScriptManager)this.FindControl("ScriptManager1");
        ScriptMgr.RegisterPostBackControl(ImgBtn);
    }
}
Jarrod
  • 1,535
  • 3
  • 16
  • 19
0

The event on which the Export to excel code is called, must make a full postback. the issue is because it does only a partial postback.

I had the same error and it got solved when i did a full postback.

Hope this helps someone.

Jackson Lopes
  • 215
  • 1
  • 5
  • 20
0

Try instead: HttpApplication.CompleteRequest() as per: http://www.c6software.com/codesolutions/dotnet/threadabortexception.aspx

They discuss the additional html being flished

Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • Switching to CompleteRequest does avoid the error, as I stated in the question, but it does not address the javascript error ” The message received from the server could not be parsed.” I did add the mentioned overrides from your link, to no effect. – Jarrod Jun 21 '11 at 18:03
  • look at the data coming back in Fiddler (www.fiddler2.com) - something may be writing to the response stream that you don't expect and you may have to buffer the output and response.clear, but try fiddler. – Adam Tuliper Jun 21 '11 at 20:35
  • Adam, I will remember to use that next time I run into an issue like this. thanks for the suggestion and input. I posted the solution, as I did find the root of the issue. Thanks again. – Jarrod Jun 22 '11 at 18:46
0

use this

   Response.Clear()
    Response.AddHeader("content-disposition", atchment;filename=fm_specification.xls")
    Response.Charset = ""
    Response.Cache.SetCacheability(HttpCacheability.NoCache)
    Response.ContentType = "application/vnd.xls"
    Dim stringWrite As System.IO.StringWriter = New System.IO.StringWriter
    Dim htmlwrite As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(stringWrite)
    GridView1.RenderControl(htmlwrite)
    Response.Write(stringWrite.ToString)
    Response.End()

instead of gridview1 you can use div

                            dont forget to add this on your page

 Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
 End Sub
Vikky
  • 752
  • 3
  • 15
  • 35
  • With the exception of Response.Charset = “” and Response.Cache.SetCacheablility(HttpCacheability.NoCache), this is identical to what I have. Perhaps not surprisingly, adding those lines had no effect. I get the ThreadAbortException unless I suppress it, and in either case I get the javascript error “The message received from the server could not be parsed.” I do have VerifyRenderingInServerForm overridden in the page. – Jarrod Jun 21 '11 at 18:04
  • did you add ValidateRequest="false" on top of your aspx source page where page class is defined? – Vikky Jun 22 '11 at 06:24
  • no, I did not. I do not see where you mentioned to do that. I was able to find the error those and have posted my answer. Thanks for your input on this issue. Much appreciated. – Jarrod Jun 22 '11 at 18:45