views:

44

answers:

1

Hi,

I am trying to change the text of a asp:textbox and collapse some ajaxToolkit:CollapsiblePanelExtenders within some ascx controls on my page as well as output a dynamically generated file. I have no problem collapsing the CollapsiblePanelExtenders and changing the text of the textbox from the codebehind or outputting a file. The problem arises when I want BOTH of these events to happen on the same postback. Unfortunately using Response.Write negates all of the other changes to the page.

Thanks in advance

+2  A: 

Here is a quick concept example of how you could update text on the screen and download a file at the same time through an AJAX postback with an UpdatePanel.

ASPX code:

<asp:UpdatePanel id="update1" runat="server">
  <ContentTemplate>
    <asp:TextBox id="textbox1" runat="server" /><br />
    <asp:Button id="button1" onclick="button1_Click" runat="server" />
  </ContentTemplate>
</asp:UpdatePanel>

C# code:

private string GenerateDownloadLink(string fileContent, string fileName) {
  // worker process will need write access to this folder
  string downloadFolder = "./download";

  TextWriter file = new StreamWriter(Server.MapPath(downloadFolder) + @"\" + fileName);
  file.WriteLine(fileContent);
  file.Close();

  return downloadFolder + "/" + fileName;
}

private void button1_Click(object sender, EventArgs e) {
  textbox1.Text = "the file download will begin shortly...";

  string fileContent = "here is the content for a new dynamically generated file";

  string fileUrl = GenerateDownloadLink(fileContent, "hello.txt");

  ScriptManager.RegisterStartupScript(this, this.GetType(), "StartDownload", "window.location = '" + fileUrl + "';", true);
}

Also check out this MSDN example.

I would also like to add that UpdatePanels will eat your soul and you should get rid of them in favor of something like calling a WebMethod via AJAX if at all possible :)

Nate Pinchot
This will not work as I need to generate the file when the button is clicked based on values in various fields on the page. I can't just redirect them to the file via javascript because it doesn't exist until after the button is clicked.
Ben
@Ben: Generate the file in `button1_Click` based on the fields on the page, save what would be the URL to the file, and then use it in the `ScriptManager.RegisterStartupScript`.
Nate Pinchot
@Nate: Could you provide some example of how to do this? I currently am writing the file out from memory and it doesn't have a URL.
Ben
@Ben: The solution is actually pretty simple. Instead of pointing `fileUrl` to a physical file location, point it to an `.aspx` file that accepts a few query string parameters (the fields you are basing your output on) and write out the file from memory there. If you don't want to use query string parameters because the field data is sensitive, you could shove the field data into the `Session`, or send them via POST with jQuery - the former being the easier of the two ways to accomplish this.
Nate Pinchot
@Nate: This solution is 90% of what I want. Do you have any suggestions on how to delete the generated file after the user has downloaded it?
Ben
@Ben: You could make a cleanup task for later, via a scheduled task. A cleaner solution would be to do something like what I suggested in the last comment. Instead of pointing the `fileUrl` to a physical file location, point it to an `.aspx` or `.ashx` (HttpHandler) and write the file out from there.
Nate Pinchot
@Nate: The .ashx solution did the trick. However, I did have to use the javascript window.open({URL OF .ashx}) method where I added the script to the page rather than the window.location = {URL of .ashx file} as the latter solution gave me the same problems as I was having intially. (The data that was supposed to be hidden by the collapsiblepanelextenders was showing even though they were collapsed). Thanks for your help.
Ben
@Ben: Thanks for the insight I will keep that in mind if I ever need to implement something similar with UpdatePanels :) Glad to hear you were able to get it working how you needed!
Nate Pinchot