HTML to PDF: Avoid having the download button in the downloaded PDF - asp.net

I have an ASP.NET page that generates a document for the user based on parameters in the URL. At the bottom of the document is a button that says "Download to PDF".
To implement that feature, I am using ABCPdf. I just feed my web page to the library and it spits out a PDF, and it works very well. Almost TOO well in fact - because the PDF includes the "Download" button itself. How can I include my entire page EXCEPT that specific button?
Here is what I have tried:
In the AddImageToURL call, I added a parameter "&pdfmode" to the URL. Then in my page load, I check for that parameter. If it is there, I say "btnDownloadPDF.Visible=False". This has no effect. I tried a similar approach by checking the page.request.form arguments to detect whether the page is posting back because of a click of the button.
'This does not work; the PDF still includes the download button
Dim pbcontrol = GetPostBackControl(Page)
Dim pdfMode As Boolean =
(pbcontrol IsNot Nothing AndAlso pbcontrol.ID = "btnDownloadPDF") _
OrElse (Not String.IsNullOrEmpty(Context.Request.QueryString("pdfmode")))
If pdfMode Then
btnDownloadPDF.Visible = False
End If

Hum, we probably need some details of how, and when the page is sent to that PDF system.
I suspect that that system takes the page URL and re-loads it?
Or does some code feed the PDF system a existing page class in code?
This suggests?
Hence on your existing page, you need a session() value, (or hidden field) and you have to set that persisted value to "hide" the button.
Then in your on-page load event, check for that session() value, and simple go mybutton.visible = false. So, that external library probably is feed a page url, and it re-renders the whole page - so in page on-load, you need to hide the button?
It just not clear how you hiding that button, but in your code behind, that may well not suffice, since the PDF library is re-loading its OWN copy of the page - hence you need code in the on-load event to hide the button.

Related

After ASP .Net Dynamically Rendered PDF, Cannot Change Page

I have a page where the user enters some information. At the bottom of the page there is a checkbox that is disabled, that says they have read the PDF to be displayed. They click on a link which dynamically renders a PDF and is downloaded by the user. After downloading the PDF a Response.End() is issued, which means nothing else can be done on the page. I want to be able to enable the checkbox after the PDF is sent.
I have tried saving the data to the Session, opening a new window, and using the Session data to send the PDF from that new window. However, IE popup-blocker blocks it.
Any ideas?
Is there anyway to use jQuery/AJAX for this? If you did you could send the request to download the PDF via the AJAX request, and then re-enable the checkbox with javascript afterwards.

CrossPost access to data

I have a search form on a page that posts back to itself and shows the results, all works fine. I now have a requirement to put the same search form on the site home page. This needs to post back to the search form and run the findResults code. Using the PostBackURL parameter on the home page form's submit button I can hit the search page ok. However, when using the following code in the Page_Load section of the search page I hit the problem of not being able to access data from the posting page as I get the following error message on the line starting "yearList.SelectedValue....": "'Site._default1.Protected WithEvents yearList As System.Web.UI.WebControls.DropDownList' is not accessible in this context because it is 'Protected'".
'#################################
'# Handle form post from Home page
'#################################
Dim crossPostBackPage As Site._default1
If Not (Page.PreviousPage Is Nothing) Then
If Not (Page.IsCrossPagePostBack) Then
If (Page.PreviousPage.IsValid) Then
crossPostBackPage = CType(PreviousPage, Site._default1)
yearList.SelectedValue = crossPostBackPage.yearList.SelectedValue
getAvailability()
End If
End If
End If
As I didn't declare yearList Protected, I don't know where to change it or how to.
Any advice would be appreciated,
Craig
dim prevYearList as ListBox = CType(PreviousPage.FindControl("yearList"),ListBox)
reference: http://msdn.microsoft.com/en-us/library/ms178139.aspx
note: the vb is a quick off the top of my head translation of my tested c# code, so don't take it literally.

How can I send a file AND the page in an HTTP response?

I have an ASP.NET page where I'm generating an Excel spreadsheet and sending that in the response (content-disposition header). That part works great, but I have a button that never becomes re-enabled because the original page isn't part of the response.
Here's the function I'm using:
Public Shared Sub WriteToResponse(ByVal theWorkBook As Workbook, ByVal FileName As String, ByVal resp As HttpResponse)
Dim theStream As New System.IO.MemoryStream()
theWorkBook.Save(theStream)
Dim byteArr As Byte() = DirectCast(Array.CreateInstance(GetType(Byte), theStream.Length), Byte())
theStream.Position = 0
theStream.Read(byteArr, 0, CInt(theStream.Length))
theStream.Close()
resp.Clear()
resp.AddHeader("content-disposition", "attachment; filename=" & FileName)
resp.BinaryWrite(byteArr)
resp.End()
End Sub
I tried not clearing the response and using AppendHeader instead of AddHeader, but the response still contains only the file.
What am I missing? Do I need to use a different header? I found this unanswered question on the ASP.NET forums; sounds like my problem.
You can't. You can fake the behaviour by opening a popup on clicking the button and have the popup serve up the file and posting back the page from the javascript. But in this manner you are effectively creating 2 requests with 2 responses.
update: if you want to disable the button when they start the download and enable it as soon as the download starts you can't really do this but you could use some trickery to make it appear like that. When they click on the download button use some javascript to disable the button and to create the popup that kicks off the file streaming. When the filestreaming function (WriteToResponse) returns set some value in the users session. In the mean time have the original page poll the server using AJAX to see if the session value is set. If it's set re-enable the button and set to the value to empty or false again (so this works a 2nd time). But this seems like a whole lot of tricks.
but I think in this case the cure is worse then the problem. I assume you want this because generating the file takes a while and you don't want users to reset the flow by pressing the button impatiently while the file is being prepared. To accomplish this I would just show a popup message in the page on button press saying something like "Your download is being prepared. This might take a minute. Thank you for your patience. (click to dismiss this message)"
You cannot send back a file and a new page in the same response.
I'm not sure how the solution fits your particular needs, but remember that you can use Javascript to enable or disable a button right before the file-creating request is sent to the server (so that, by the time spreadsheet download begins for the user, the button is already in the state you want it in).

asp.net make button show different view of MultiView AND download a file

I have a page on my site on which users have to fill out details before they can download a document. The user details section is on the first view in a MultiView control.
After filling out their details I'd like the user to click a button which will show them a file download prompt (I've done this successfully with an ashx handler) then redirect them to the second view page of the MultiView which will say "thank you for downloading" or something like that.
I've tried the usual Response.Redirect("~/DownloadHandler.ashx"); within the button click event handler, but obviously this prevents the page completing the postback and showing the last page of the MultiView.
Is there a way around this, or should I just change my UI to accommodate this?
EDIT:
I've concluded that it's better to just provide a hyperlink to the document (on my confirmation page, and change the wording accordingly) as this provides a consistent user experience independent of the browser they're using.
Go ahead and take them to the second view of the MultiView. Add a javascript method that will download the document, and trigger it from your codebehind.1 E.g.,
In your page:
<script>
function downloadFile(url) {
window.location = url;
//you could also try window.open(url, 'Download')
}
</script>
In your code behind:
script = string.Format("downloadFile('{0}');", "DownloadHandler.ashx");
Page.ClientScriptManager.RegisterStartupScript(typeof(Page), "download", script, true);
You could also add a delay (using setTimeout) before the file is downloaded.
More info:
Initiating a file download that works well, even in IE?

Close Browser Window after Form Post

Here's my situation.
I have a button on my ASP.NET webform. This button creates a new browser window pointing to a page which has a lot of hidden fields (which are dynamically generated). This form submits itself to SQL Reporting Services on the bodies onload event. This works fine and the report is displayed in this new window.
However, now I want to still POST a form to SQL Reporting services but I want to get back an excel spreadsheet. So I add another hidden input with a name of rs:Format and value of Excel. This works and the user gets the option to download the excel file.
However they are now stuck with the extra window that was created. How do I get around this? I've tried creating the dynamic form and POST in the same window, but then they see the (empty) page with the form, and not the page they generated the report from. I've tried closing the window that I've created but I don't know where to put the javascript to do this. If I put it on the onload, then the window closes without the form being submitted.
Any ideas for what to do here?
Edit: What I was doing here wasn't the best way of getting the result I needed. I ended up using a WebRequest to get the excel report from Reporting Services instead posting a form, therefore I didn't need the second window afterall.
Don't close the browser. It belongs to the user, even if you opened it. Closing it can make them mad.
Do redirect to a page the communicates to the user that you're done with the window. There you can provide a (javascript-based) link that make closing the browser a little easier if you want, though closing a browser window is generally pretty easy.
By the way, if the popup doesn't contain any useful output, what you may want to do is submit your form into a small Iframe within the page. This way there's no need to close a window, as the frame can be made invisible.
When user wants an Excel file, there's no need to pop up another window. I assume selection of Excel file or HTML report is done in some HTML control like a radio button or a checkbox. So, before doing anything, check the value of that radiobutton/checkbox with javascript and do the appropriate action. Something like:
function getReport(excelFormat)
{
if (excelFormat)
document.form1.target = '_blank';
else
document.form1.target = '_self';
document.form1.submit();
}
What if the button did an Ajax request back to the original page and got the hidden field values. You could then construct another form on the page with the hidden fields using javascript and submit it -- with the download option. Since the request will return an application/ms-excel file, it shouldn't refresh the current page but the download should still occur. You'd need to make sure that the button click didn't cause a postback by returning false from the client-side function. Note that this only works if the post of the generated form results in a download, not a new html page.
<script type="text/javascript">
function submitReport( button ) {
PageMethod.SubmitReport(onSuccess,onFailure,{ control: button });
}
function onSuccess(values,ctx) {
var form = document.createElement('form');
form.action = reporting-services.url;
form.method = 'post';
document.body.appendChild(form);
.... add hidden fields to form from returned values
form.submit();
document.body.removeChild(form);
}
function onFailure(error,ctx) {
... pop up some error message....
}
</script>
...
<asp:Button runat="server" id="reportButton" ClientClick="submitReport(this);return false;" Text="Report" />
Generally it's ok to close any popup window that your app has created.
This can be done with window.close() (which will pop up a confirmation if the window was not created by script).
If you want to be sure that the download is successful before closing the window, you will need to perform some server-side magic - have your server keep track of the download in progress, and poll it via AJAX from the popup window until the download completes.
Once the server tells you it's done, the window can be closed.

Resources