Post Back does not work after writing files to response in ASP.NET
What I have?
I have an ASP.NET page which allows the user to download file a
on a button click. User can select the file he wants from a list of available files (RadioButtonList) and clicks on download button to download it. (I should not provide link for each file that can be downloaded - this is the requirement).
What do I want?
I want the user to download multiple files one by one by selecting the required radio button and clicking on the button.
What problem am I facing?
I can download the file for the first time properly. But, after downloading, if I select some other file and click on the button to download it, click event of the button does not post back and the second file will not be downloaded.
I use the following code on the button click event:
protected void btnDownload_Click(object sender, EventArgs e)
{
string viewXml = exporter.Export();
Response.Clear();
Response.AddHeader("Content-Disposit开发者_运维问答ion", "attachment; filename=views.cov");
Response.AddHeader("Content-Length", viewXml.Length.ToString());
Response.ContentType = "text/plain";
Response.Write(viewXml);
Response.End();
}
Am I doing something wrong here?
Same problem can be replicated in IE6, IE7 and Chrome. I think this problem is browser independent.
I had this same issue with sharepoint. I have a button on the page that sends a file and after clicking the button, the rest of the form was unresponsive. Turns out it is a sharepoint thing that sets the variable _spFormOnSubmitCalled to true to prevent any further submits. When we send a file this doesn't refresh the page so we need to manually set this variable back to false.
On your button in the webpart set the OnClientClick to a function in your javascript for the page.
<asp:Button ID="generateExcel" runat="server" Text="Export Excel"
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />
Then in the javascript I have this function.
function setFormSubmitToFalse() {
setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
return true;
}
The 3 second pause I found was necessary because otherwise I was setting the variable before sharepoint set it. This way I let sharepoint set it normally then I set it back to false right after.
Offhand, what you're doing should work. I've successfully done similar in the past, although I used a repeater and LinkButtons.
The only thing I can see that's different is that you're using Response.Write()
rather than Response.OutputStream.Write()
, and that you're writing text rather than binary, but given the ContentType
you specified, it shouldn't be a problem. Additionally, I call Response.ClearHeaders()
before sending info, and Response.Flush()
afterward (before my call to Response.End()
).
If it will help, here's a sanitized version of what works well for me:
// called by click handler after obtaining the correct MyFileInfo class.
private void DownloadFile(MyFileInfo file)
{
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "application/file";
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
Response.AddHeader("Content-Length", file.FileSize.ToString());
Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
Response.Flush();
Response.End();
}
You may want to consider transferring the file in a binary way, perhaps by calling System.Text.Encoding.ASCII.GetBytes(viewXml);
and passing the result of that to Response.OutputStream.Write()
.
Modifying your code slightly:
protected void btnDownload_Click(object sender, EventArgs e)
{
string viewXml = exporter.Export();
byte [] bytes = System.Text.Encoding.ASCII.GetBytes(viewXml);
// NOTE: you should use whatever encoding your XML file is set for.
// Alternatives:
// byte [] bytes = System.Text.Encoding.UTF7.GetBytes(viewXml);
// byte [] bytes = System.Text.Encoding.UTF8.GetBytes(viewXml);
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
Response.AddHeader("Content-Length", bytes.Length.ToString());
Response.ContentType = "application/file";
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.Flush();
Response.End();
}
A simple way to do this without removing Response.End
is to add client-side js to do the page refresh. Add the js to your button's onclientclick property.
e.g.
onclientclick="timedRefresh(2000)"
then in your html..
<script type="text/JavaScript">
<!--
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
// -->
Remove Response.End()
and let the response end naturally within the ASP.NET ecosystem.
If that does not work, I would recommend putting the button in a separate <form>
and post the required data to a separate HTTP handler. Setup the HTTP handler to export the XML instead of a web page.
I had same problem. Function to perform simple Response.Writer("") on Button Click event on aspx page was never firing.
Method in class:
public test_class()
{
public test_class() { }
public static void test_response_write(string test_string)
{
HttpContext context = HttpContext.Current;
context.Response.Clear();
context.Response.Write(test_string);
context.Response.End();
}
}
ASPX Page:
protected void btn_test_Click(object sender, EventArgs e)
{
test_class.test_response_write("testing....");
}
While I was trying to find the reason, I just called same function on Page_Load
event it worked.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
test_class.test_response_write("testing....");
}
}
Investigating the issue I found out that Master Page of that aspx page's body was under <asp:UpdatePanel>
.
I removed it, and it worked on Button_Click
Event. I would recommend you to check that too.
Check at https://multilingualdev.wordpress.com/2014/08/19/asp-net-postback-after-response-write-work-around-solution/
When sending a file to client and using response.write in ASP.Net the developer is unable to do anything else after the file is sent. There are other work-arounds like adding a javascript onclick function that would call a function after the client gets the file, which is similar to adding a meta refresh to the when the function to send the file is called (e.g. Response.AppendHeader(“Refresh”, “5;URL=” & HttpContext.Current.Request.Url.AbsoluteUri))
But those weren’t giving me the look that I wanted. So I used a combination of those work-arounds to come up with this solution:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
checkSendFile() ‘each time page loads it will check to see if it needs to send the file
If (Not IsPostBack) Then
‘this spot is not be executed after a form submit (postback); which means you can put
‘ the checkSendFile() in here if you want
end If
End Sub
Private Sub checkSendFile()
Dim sendFile As String = Session(“SENDFILE”) ‘ first we get the session file to see if its time
‘ to send a file
If Not sendFile Is Nothing Then
If sendFile = “YES” Then
Session(“SENDFILE”) = “” ‘here we clear the session file so it doesn’t send again if
‘ refreshed
sendClientFile() ‘ function to send the file to client
End If
End If
End Sub
Protected Sub btnGetFile_Click(sender As Object, e As EventArgs) Handles btnGetFile.Click
‘this is where the client clicks on a button or link or something that submits the form and
‘ request a file to be sent to them
Session(“SENDFILE”) = “YES” ‘ we set a session variable flag
‘then we update the GUI, or run any other method that we wanted to do after client gets file
me.lblMsgToClient.text = “Thank you for downloading file.”
RefreshPage() ‘ then we refresh the page instantly (this is where post back will update values
‘ and interface, then send file)
End Sub
Private Sub RefreshPage()
‘ here we instantly add a refresh meta tag to the header with zero seconds to refresh to the
‘ same url we are currently at
Response.AppendHeader(“Refresh”, “0;URL=” & HttpContext.Current.Request.Url.AbsoluteUri)
End Sub
Private Sub sendClientFile()
‘here you will have your file and bytes to send to browser from either file system or database
‘then you can call sendToBrowser(…)
End Sub
Private Sub sendToBrowser(ByVal fileName As String, ByVal contentType As String, ByRef fileBytes As Byte())
‘this function is just the normal send file to client
Response.AddHeader(“Content-type”, contentType)
Response.AddHeader(“Content-Disposition”, “attachment; filename=” & fileName)
Response.BinaryWrite(fileBytes)
Response.Flush()
Response.End()
End Sub
精彩评论