Now let’s assume you put the GridView in an UpdatePanel. All those Response calls noted above are things that the PartialPageRendering and UpdatePanel don’t know what to do with because they were expected something like the page that made the request. So we need to work around the issue. I found some solutions on the internet, but didn’t really find them very easy or straight forward. So, I came up with my own.
Solution 1
One solution is to put the Download button outside the UpdatePanel. This tends to work best, but is not always possible.Solution 2
If you can’t do solution 1, then consider faking it. What I mean is move the Download button which in my case is implemented as a LinkButton outside the UpdatePanel and hide it using css. Then add a Hyperlink inside the UpdatePanel. Now, on your page load you can set the hyperlink to have the same postback url as the LinkButton that is outside the UpdatePanel. That way when you click the hyperlink inside the UpdatePanel you are effectively doing the same thing as if you clicked the hidden LinkButton that is outside the UpdatePanel. Fairly simple.Here is the snippets of code to help you see what I am talking about.
Here is the HyperLink that is inside the UpdatePanel and is also the button that you will be clicking in the Browser.
<asp:HyperLink ID="btnExportToExcelClicker" runat="server" Text="Export all rows to Excel" />
Here is the LinkButton that is invisible to the user and is outside the UpdatePanel
<asp:LinkButton ID="btnExportToExcel" runat="server" onclick="btnExportToExcel_Click" Text="Export all rows to Excel" style="display:none;" />
Here is the code-behind. In my code btnExportToExcelClicker is the button that is in the UpdatePanel and btnExportToExcel is the button that is outside the UpdatePanel. You will actually be clicking btnExportToExcelClicker because btnExportToExcel is hidden.
protected void Page_Load(object sender, EventArgs e)
{
btnExportToExcelClicker.NavigateUrl = Page.ClientScript.GetPostBackClientHyperlink(btnExportToExcel, null);
}
This technique uses GetPostBackClientHperlink and can be expanded for other purposes and other controls. In some cases you may need to consider using GetPostBackEventReferences, though I haven’t tried it.
UPDATED: November 5, 2013
Solution 3
This is my new favorite solution due to its simplicity. This involves creating a new page in your application. Call it ReportDownload.aspx (or whatever you desire). It is critical that it not have an update panel. Best choice is usually to not even use a master page for this. The reason is that we are not going to use anything on the ReportDownload.aspx file. We will however change the ReportDownload.aspx.cs file. On the page load just put your download streaming code that would be something similar to the following:
var response = Page.Response;
response.Clear();
response.AddHeader("content-disposition", string.Format("attachement; filename=\"{0}\"", "Report.pdf"));
response.ContentType = "application/octet-stream";
response.WriteFile(@"c:\temp\DB.pdf");
response.End();
You just need to put this in the Load or PreRender events. To test this, just go to the new page you created in your favorite browser. You should see the file you specified in the code above. Now that you know that going to the url works, it is just a matter of using that url anywhere on a page (including in an UpdatePanel). I used it in LinkButton or HyperLink. You can pass a code (i.e. a record id, etc) in the url to generate the url. The nice thing is you can also incorporate security on the ReportDownload.aspx as well.
7 comments:
Completely and utterly does not work for me. Seemed like a good idea. I'll keep looking into what I might be doing wrong
Good, It worked for me
works great, cheers.
Great Work
Great article, great update!
Just use a HyperLink with targeg="blank" to the download page that uses an encrypted querystring value of the filename and | and the current datetime (to make the encrypted URL querystring diff every time).
Then, on Download page code behind, decrypt the querystring and get the filename (first param in the decrypted querystring, split by the VertBar |) and then use the Response code...
If you can’t do solution 1, then consider faking it. What I mean is move the Download button which in my case is implemented as a LinkButton outside the UpdatePanel and hide it using css. Then add a Hyperlink inside the UpdatePanel. Now, on your page load you can set the hyperlink to have the same postback url as the LinkButton that is outside the UpdatePanel. That way when you click the hyperlink inside the UpdatePanel you are effectively doing the same thing as if you clicked the hidden LinkButton that is outside the UpdatePanel. Fairly simple.
Post a Comment