I have a page that has a button:
<button id="btnExport1" runat="server" class="btn btn-success" style="width: 120px;" OnServerClick="btnExport_Click">Export</button>
The btnExport_Click method prepares an Excel file which is then sent to browser using the following code
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
var attachment = String.Format("attachment; filename=\"SR_ChargeExport_{0:yyyy-MM-dd_HH-mm-ss}.xlsx\"", DateExtensions.CurrentDisplayTime());
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Current.Response.WriteFile(filename);
HttpContext.Current.Response.Flush();
if (deleteFile)
File.Delete(filename);
HttpContext.Current.Response.End();
There is also a LinkButton on the page which when clicked runs some javascript on the page to open up a Telerik RadWindow and passes in the url of a new page. On this page there is a LinkButton that looks like this:
<asp:LinkButton ID="btnUpdate" CssClass="btn btn-success" runat="server" OnClick="btnUpdate_Click"><span>Add Comment</span></asp:LinkButton>
And in btnUpdate_Click there's some code that basically saves a comment and closes the RadWindow.
The problem I'm having is that after you click the Export button to download a file, if you then add a comment by clicking the button in the RadWindow another Excel file is downloaded. The AddComment code does get run but then the Export code gets run again straight after. I'm thinking it's something to do with not being able to post back to the page after writing to the browser in the Export code.
Make the request for your Excel download be asynchronous via an HTTP Handler, thus you can do this instead:
Markup:
<a href="#" class="btn btn-success"
src="PATH_TO_YOUR\HTTP_HANDLER.ashx">Export</a>
ExportToExcelHandler.ashx:
public class ExportToExcelHandler : IHttpHandler {
public void ProcessRequest (HttpContext context)
{
context.Response.AddHeader("content-disposition","attachment; filename=excelData.xls");
context.Response.ContentType = "application/ms-excel";
// Put logic here to create Excel download
// Stream it back to browser
}
public bool IsReusable
{
get
{
return false;
}
}
}
After further investigation I found out that there was javascript being run for the OnClientClose event of the RadWindow. In there it was submitting the form (in order to update the comments on the page) so I changed it to do a 'location.reload()' instead.
Related
I have this aspx script for the button for pop-up:
<asp:Button ID="btnNewEntry" Text="Post Code Search" OnClick="btnNewEntry_Click" runat="Server" target="_blank"/>
and behind:
protected void btnNewEntry_Click(object sender, EventArgs e)
{
ClientScript.RegisterStartupScript(this.Page.GetType(), "", "window.open('../search/postcode_search/Default.aspx?code="+ p +"','Post Code Search','width=800,height=300,left=100,top=100,resizable=yes'); popup_handle.focus();", true);
}
But as the button is clicked the pop-up is opened but the parent page is refreshed. Why it's so? any work around?
Page got refreshed when a request to server is made, and server controls like Button has a property AutoPostback = true by default which means whenever they are clicked a trip to server will be made. Set AutoPostback = false for insert button, and this will do the trick for you.
or
Add OnClientClick="return false;" ,
<asp:button ID="btninsert" runat="server" text="Button" OnClientClick="return false;" />
Perhaps a little explanation of what is actually happening with your code will help. We have already discussed the auto postback, so you know that clicking that button will send the event back to the server. The page initializes again and reloads the view state and all of the posted data. After that, the button click event is handled.
At this point, your code writes the window.open script to the page. Keep in mind this is no where specific. This is just script that is added some where on the page and executed. The view state then gets updated and the page is sent back to the client. If the user reloads the page, that script is going to execute again.
Your best bet is going to be converting that to a client side button only. Find a way to get the necessary data back from the server before loading your popup. The easiest way to do that is make an AJAX call and open your pop up on success from your end point.
Try this.Updated one.
<asp:Button ID="btnNewEntry" Text="Post Code Search" OnClick="btnNewEntry_Click" runat="Server" target="_blank"
OnClientClick="javascript:window.open('../search/postcode_search/Default.aspx?code=+ p','Post Code Search','width=800,height=300,left=100,top=100,resizable=yes').focus();return false;"/>
Issue was due to "+ p +".
So as advised, i decided to go to client side. Here is my script:
<button onclick="OpenPopup()" type="button">Post Code Search</button>
and javascript code above it:
<script>
function OpenPopup() {
var getQueryString = function ( field, url ) {
var href = url ? url : window.location.href;
var reg = new RegExp( '[?&]' + field + '=([^&#]*)', 'i' );
var string = reg.exec(href);
return string ? string[1] : null;
};
var str = getQueryString('code');
if (str != null) {
p = str.replace(/%20/g, ' ');
}
else {
p = "";
}
var url = "../search/postcode_search/Default.aspx?code=" + p;
window.open(url, "Post Code Search", "toolbar=no, location=no,status=yes,menubar=no,scrollbars=yes,resizable=no, width=750,height=400,left=430,top=100");
return false;
}
</script>
so basically what it does, it grabs parameter from parent window url and adds to popup window url. My parent window url:
/Customer.aspx?code=V6E%20111&firstname=MyName
I hope it helps for others as well. Thanks for help guys.
Im trying to use an asp:progress so when I click on my asp:button it calls an ashx file which write a CSV response.
So far when I click on the button, the animation shows properly and the download start. However I can't seem to stop the animation when the file start downloading (when I get the response from the ashx file).
Here is the aspx :
<asp:Content ID="Content2" ContentPlaceHolderID="MainPlaceHolder" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<p>Download a CSV file</p>
<asp:Button ID="Button2" runat="server" Text="Download"
CausesValidation="False" onclick="Button2_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="UpdateProgress1" AssociatedUpdatePanelID="UpdatePanel1" runat="server">
<ProgressTemplate>
<div id="AlertDiv" style="background:White">
<asp:Image ID="imgLoading" runat="server" ImageUrl="css/smoothness/images/animated-overlay.gif" Width="34px" />Loading...
</div>
</ProgressTemplate>
</asp:UpdateProgress>
</asp:Content>
Here is the Button2_click function :
protected void Button2_Click(object sender, EventArgs e)
{
try
{
Response.Redirect("ProductsHierarchyDownload.ashx");
}
catch (Exception ex)
{
//log
}
}
And here is the ProcessRequest function from the ashx file :
public void ProcessRequest(HttpContext context)
{
string attachment = String.Format("attachment; filename=Hierarchie des produits au {0}.csv", DateTime.Today.ToShortDateString());
context.Response.AddHeader("content-disposition", attachment);
context.Response.ContentType = "text/csv";
context.Response.AddHeader("Pragma", "public");
context.Response.ContentEncoding = Encoding.GetEncoding(1252);
context.Response.Write(DemandeTarifImageBLL.DataTableToCSVString());
}
I've tried to use javascript and the property endRequest, beginRequest and initializeRequest event of the PageRequestManager Class (I found some conde snippet here) but nothing has worked for me so far.
How do I force the animation to stop when the download starts ?
Although I was not able to try and see if its working but by my previous experience I can suggest the following. Try changing your code as follows:
public void ProcessRequest(HttpContext context)
{
string attachment = String.Format("attachment; filename=Hierarchie des produits au {0}.csv",
DateTime.Today.ToShortDateString());
context.Response.AddHeader("content-disposition", attachment);
context.Response.ContentType = "text/csv";
context.Response.AddHeader("Pragma", "public");
context.Response.ContentEncoding = Encoding.GetEncoding(1252);
context.Response.Write(DemandeTarifImageBLL.DataTableToCSVString());
context.Response.Flush();
context.Response.End();
}
Adding Flush and End clears the buffer and marks the response end respectively. This way the client would reach a definite conclusion that the Request has been completely processed.
Also you can control the update progress with the client side script, here is a sample code:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequest);
function EndRequest(sender, args) {
if (postBackElement.id == 'Panel1Trigger') {
$get('UpdateProgress1').style.display = 'none';
}
}
The above js code adds an handler for update panels end request event and on the function closes the Update progress.
Try putting the contents of you ProcessRequest function of your handeler to the button click event, and do remember to add Flush() and End function for the response.
EDIT 1:
On looking further in stack overflow I found the following link with the issue similar to yours, and this confirmed my assumption that you can not have a redirect inside an update panel:
asp:UpdateProgress never goes away after clicking on downloadable content inside a repeater
Hope this helps.
Try redirect to ashx from javascript.
ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "downloadFileExport", "javascript:window.location ='" + ResolveUrl(downloadUrl) + "';", true)
This was solved my issue too.
In my ASP.Net Web Forms application the progress text kept showing even after the process was done. I was able to fix that in Dev environment by increasing the timeout in the ScriptManager. Example below.
When I try the following code with a postback the file download takes place normally:
FileInfo file = new FileInfo("C:\\a.txt");
Response.ClearContent();
Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
Response.AddHeader("Content-Length", file.Length.ToString());
Response.ContentType = "text/plain";
Response.TransmitFile(file.FullName);
Response.End();
However if I put the above code inside a public static web method and call it with AJAX I get error, like "Process was being aborted".(Of course to get the current response I write HttpContext.Current.Response) This makes me think that the nature of the two responses are different. My question is if they are different, then what exactly is/are different? Is there a way to achieve the same thing with AJAX?
The browser isn't going to receive the file via an XHR (Ajax) call. You will want to return the file location and then send the browser to that file via window.location or window.open.
Edit: Here's a Web Forms sample. My Web Forms skills are a little rusty since I've been using MVC now; the syntax is off the top of my head so you might need to fix it up a little.
ASPX Page
<div id="whateverIsContainingYourDialog">
<form id="mikeJMIsAwesome" runat="server">
<asp:TextBox id="firstName" runat="server" />
<asp:TextBox id="lastName" runat="server" />
<asp:Button id="submit" runat="server" />
</form>
</div>
Server Side Code
protected void submit_OnClick(object sender, EventArgs e) {
//Your logic for creating the file and the code you originally posted for serving the file.
}
What Ek0nomik said, file downloads are handled by the browser and cannot be handled through Javascript. The responses are both identical they are are both just http responses - you can verify this with fiddler or another tool (http://www.fiddler2.com/fiddler2/).
Essentially you ajax method will not be able to handle receiving a file and will certainly not have the permissions to assemble it and store it on you hard drive.
You can 'fake' a user clicking on a link using some Javascript.
Please check this similar question for an answer. I've pasted the answer from it below.
starting file download with JavaScript
We do it that way: First add this script.
<script type="text/javascript">
function populateIframe(id,path)
{
var ifrm = document.getElementById(id);
ifrm.src = "download.php?path="+path;
}
</script>
Place this where you want the download button(here we use just a link):
<iframe id="frame1" style="display:none"></iframe>
download
The file 'download.php' (needs to be put on your server) simply contains:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
?>
So when you click the link, the hidden iframe then gets/opens the sourcefile 'download.php'. With the path as get parameter. We think this is the best solution!
I have an aspx page which has several controls. When I click a button on this page,
I need to get the values of the textbox and dropdowns and do some processing and pass it on to another aspx page. The second aspx will do further processing and generate a pdf to download.
I don't want the user to be redirected to the second page. I simply want the pdf download to appear in a new window.
How can I achieve this?
You need to set the Content-Disposition http header and return the pdf directly.
Like this:
Response.ContentType = "application/x-download";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", fileName));
Response.WriteFile(filePath + fileName);
Response.Flush();
Response.End();
Note: Don't set the Content-Disposition to application/pdf as this is recognized by many browsers and they will try to open it with the pdf-reader embedded in the browser.
How to post to second page on button click?
Set the PostbackUrl on your button click like this:
<asp:Button
ID="Button1"
PostBackUrl="~/TargetPage.aspx"
runat="server"
Text="Submit" />
You can read values from your current page on target page by accessing the controls using the PreviousPage property as follows:
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
I have a link in aspx page and when i click on it,it shows a popup: open,save,cancel
but when i click cancel on that aspx page no other link works on that page.
code so far:
protected void method1()
{
byte[] byterendered = _Filename.OpenBinary();
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.AddHeader("Content-Disposition", "attachment;filename=abc.jpg");
Response.CacheControl = "Public";
Response.BinaryWrite(byterendered);
Response.End();
}
aspx code
<asp:Linkbutton id="link1" runat="server" onClick="method1" Text="LinkA"/>
<asp:Linkbutton id="link2" runat="server" onClick="method2" Text="LinkB" />
As the comments to your question have indicated, the reason is because your Response is being ended after the file dialog shows up. Once the response ends, any other actions on your page will not be registered. I ran into this myself while implementing a download function for my SharePoint app.
Basically, what you want to do is have your link buttons perform a window open script, instead of directly running the file transfer, like the following.
<asp:LinkButton id="link1" runat="server" onClick="window.open('TARGETURL'); return false;" Text="LinkA" />
Replace TARGETURL with an aspx page URL. Then, create a new ASPX page for the URL you specified. It will be pretty much empty, all you need are two lines.
<%# Assembly Name="YOURFOURPARTASSEMBLYSTRINGHERE" %>
<%# Page Language="C#" Inherits"YOURNAMESPACE.DOWNLOADCODE" %>
Replace YOURFOURPARTASSEMBLYSTRINGHERE with, of course, the four-part assembly string for your code. YOURNAMESPACE.DOWNLOADCODE will be replaced with the namespace and class that you will create for the page. The class will need to inherit the base page type, I personally used LayoutsPageBase since that's a perfect thing to use in a SharePoint app. All this class needs is an OnLoad method like the following.
// Don't actually name your class DOWNLOADCODE.
public class DOWNLOADCODE : LayoutsPageBase
{
protected override void OnLoad(EventArgs e)
{
byte[] byterendered = _Filename.OpenBinary(); //More on this afterwards
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.AddHeader("Content-Disposition", "attachment;filename=abc.jpg");
Response.CacheControl = "Public";
Response.BinaryWrite(byterendered);
Response.End();
}
}
You will have to retrieve _Filename in this new page, of course. The best way to do this is to take whatever parameters you use to determine _Filename in the first place, and pass it as part of the URL query string.
Using this, clicking the link button will open a new window, but since all this page does it have a file response, it will just open the file dialog and be done with it. Meanwhile, your original aspx page will not have ended its response, so it can continue whatever function you need it to.