In my ASP.Net application I have a requirement that when a user clicks on an UI element we generate a PDF for them which they can download. This is currently implemented by doing a form post to an ashx page. This page essentially inspects the form and then executes the correct server side page which either results in HTML or a PDF document of that pages HTML.
On the client I know ahead of time if we are going to be getting a PDF or HTML, when its an HTML I open a new window and direct the form post to that window and all works well. When its a PDF I don't change the target for the form and it remains on the current page.
This works, the user is presented with a save dialog, and the current page is not changed or lost.
The problem I have is that generating the PDF takes anywhere from 1-15 seconds. What I want to do is popup a please wait dialog. Displaying the popup is going to be easy, what I am not sure of is how do I know to close the popup? The popup will be a div in the current page.
The popup can have a client side timer which polls the server for task completion. The long running server task should update the progress in a database table or a server cache object which can be accessed by the polling service.
Couple of old articles from MSDN magazine. You should be able to use the same concepts with newer libraries like asp.net Ajax.
Reporting Task Progress With ASP.NET 2.0
Simplify Task Progress with ASP.NET "Atlas"
just have some javascript on the client side and let it show some animated GIF for 1-15 seconds (your choice) and close itself after the designated time.
Gulzar's suggestion was spot on. I have a simple ajax enabled wcf service which checks a session variable. My ashx page sets the variable to false when it starts processing and then true when its done.
I think there might be a race condition if the client checks before we set the session item to false; however, there are ways around that if we modify the service to set the session item to false after a client gets an im done response.
The tricks is still going to be figuring out what the intervalon the client should be. If we set it to low the user could save the file and then see the still processing message. I'm debating myself between half a second and a second. Anything less then a half a second seems unnessecary.
You said:
When its a PDF I don't change the
target for the form and it remains on
the current page.
If that is the case then the original page will be gone when the PDF is opened. In that situation I would have a loading animated gif and open it using Javascript into a div tag overlaying the rest of the page. You would not need to close it, so no timer or polling needed. It would just be gone when the page is gone.
Related
I have a form that dynamically generates a PDF based on database data. But I don't want to navigate away from the form whilst the PDF is generated and downloaded. So I am using response.redirect to call the .aspx page that generates the PDF and serves it via stream (Have done for many years) so there may be a better option out there now. However I have found people are logging out before the PDF has been sent to the browser which is causing issues.
Is there a way to detect when the reponse.redirect has finished and the file has been downloaded?
I have tried using postmessage and a listener but this doesn't work.
I've also tried setting up and EndRequestHandler as below in my main form:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler) ;
But this hasn't worked either. The browser is aware as as the tab with the main form has a progress icon in, so there must be a way to intercept the complete event.
Might not be accurate like you want it but I do something sort of similar. When the button is clicked, a "Please Wait..." message appear until the file is ready to be downloaded. The way I do it is the client wait for a cookie. When the server is ready to send the file (after processing) it sets a cookie. Even if the cookie was set in a different request, the client still gets the updated value.
I can't believe how many articles I have read and example code I've tried to understand, with no success in accomplishing what I need to do. Hopefully someone can help me out by providing some example code or pointing me to another resource.
I am working in ASP.NET 4.0, C# using VS 2012 Express. The project is a web site. I have a UI page that contains checkbox controls and dropdowns for a user to set preferences. At the bottom of the page is a checkbox for the user to agree to some terms and conditions and an image button they click to get the results based on their preferences. This all works and so does the results page.
The problem is that the results page takes as much as 90 seconds to complete. I can't just leave the user with a "Loading..." on the status bar of their browser. So what I am wanting is:
User clicks to get results
Results page loads immediately
Once results page has loaded, a call is made to server that begins the 90 second process.
User is provided a status display of the progress.
Once process completes, a link is presented for them to view their results.
I see many examples with varied approaches. Most of them require the user to click a button to begin the process. I don't want the user to have to click another button - I just want the process to begin when the results page is finished loading.
Additionally, I'm looking for an idea of how to code the client page to make calls to the server to obtain the status of the process. Preferably a percentage value and a text message for each step of the process. Ie:
25%
Compressing files...
I've seen some Web Method examples, but I don't think I've seen a single one that demonstrates beginning the process initially without having to click a button to invoke it initially. I considered putting the Javascript call in the , but it is contained in a Master.Master that is used by many other pages.
Does anyone know of any code examples that might help me accomplish this sort of thing?
I found a really nice solution from EssentialObjects.com. Their progress bar control is free, although I needed their CallBack custom control to do what I wanted - the CallBack control is not free.
Hope this helps someone else out!
I have a performance issue where we have a 2 page setup as part of a workflow in a bigger system. This section is dedicated to rendering reports allowing users to chose their own parameters.
Page1.aspx collects parameter information for a report. It takes the information submitted on a form and validates it. If it validates OK, it stores the selections in the DB as XML, then redirects to Page2.aspx with the run id in the query string. Simple enough, performance is great.
Page2.aspx pulls the ID out of the DB and hydrates a Crystal ReportDocument object (taking milliseconds) then we call ExportToHttpStream which then renders the report as a PDF or DOC or XLS download (output format is determined in Page1.aspx). The performance of the ExportToHttpStream method is very poor due to the way our reports are written and DB indexes on the target system. This is outwith my control at the moment but I am promised that they are being worked on.
So the problem is, that when the submit button in Page1.aspx is pressed, the user experiences a very long delay before the download starts. It is then compounded by the user pressing the submit button again thinking there is a problem.
I think what I need to do is have Page1.aspx redirect to Page2.aspx. Page2.aspx should render the master page furniture and a loading div, and the report should render asynchronously somehow in the background before the save dialogue automatically pops up, after this i'd like to change the loading div to a 'Report generated, click here to go back'.
If this is the best way to achieve this, how can I load a full page, then request the report asynchronously? I'm open to any suggestions here.
You could use ajax to load the report on Page2.aspx and show a loading message while it's processing.
Look at the jQuery.load() method. This might be the easiest way to accomplish what you are trying to do.
Page1.aspx - collect parameters
Page2.aspx - report view, calls Page2Details.aspx via ajax.
Try loading Page2.aspx inside iframe and use jQuery to display waiting indicator and hide it after Page2.aspx download
Whilst both answers gave me some ground to go out and research in the right direction. My solution included using the fileDownload plugin from John Culviner to facilitate a similar solution:
jQuery fileDownload by John Culviner
This allowed me the following page structure:
Page1.aspx, gathers and validates parameters for the report and puts them into Oracle.
Page2.aspx, whilst passed in the runid (pointer to the parameters in the db) via the query string setup 3 hidden divs. Loading, Error and Success.
The script mentioned above was employed at this point. jQuery firstly sets the loading div visible then calls the plugin. The plugin dynamically creates an iframe and downloads the binary (xls/doc/pdf) from Page3.aspx. It then fires a success callback or failure. The success callback is fired by means of a cookie set at the end of the response in Page3.aspx.
I believe the plugin mentioned downloads using a 'text/plain' AJAX call in jQuery avoiding the limitation of there not being an octet-stream equivalent in AJAX.
It works, its not the cleanest solution by any means, it doesn't degrade one bit, but provides the users on our controlled intranet with an extremely responsive and pleasing UI.
How does the ASP.NET page rendering happens from Server to Client Browser? The question is, consider the Page has a Header and Footer which are User controls and contain many server controls.
Does ASP.NET start sending the HTML to client browser, once it gets some of the controls being rendered and converted in their respective HTML? Or does it wait for the whole page to be rendered and converted in HTML on Server, and then it sends back the Page HTML to the browser.
I am seeing that the "Page Title" of our website is shown much before and then the page takes too much time in loading completely. I want to be clear on this concept whether its server that is taking time or the client side scripts, images etc.. are the culprit. Accordingly we will start the optimizations.
Specifically I am interested in knowing how the outputstream (in response object) is sent to the Client Browser? Is the outputstream flushed once whole page is rendered in outputstream or it is sent to client in batches (i.e. few controls rendered and sent to browser via outputstream --> then some more controls are rendered and so on...)?
Sorry if am not clear enough on the problem.
in terms of debugging you can turn .NET tracing on to see whats taking the time on the server side,
and use google chrome or firebug for firefox to see whats taking the time on the client side.
I believe this is controlled by Response.BufferOutputor something similar(no reference at hand) to determine if it should start sending out HTML as soon as it's ready or if it should store it in a buffer and wait until everything is done and then send it.
The answer I was looking for was regarding the rendering way, how is stream sent to client, there could be two ways, Either directly sending it as soon as it is generated, in multiple chunks, Or cache and store until whole page is rendered and then send it to client.
I got the answer at: http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new
"Normally ASP.NET buffers the response bytes as they are created by an application. ASP.NET then performs a single send operation of the accrued buffers at the very end of request processing.
If the buffered response is large (for example, streaming a large file to a client), you must periodically call HttpResponse.Flush to send buffered output to the client and keep memory usage under control. However, because Flush is a synchronous call, iteratively calling Flush still consumes a thread for the duration of potentially long-running requests."
Thank you all for your help!!!
User controls are rendered before controls on the .aspx page itself.
Take a look at the Page Life Cycle
Fiddler should help determine where the bottleneck is, if you're seeing the page title show up but the page doesn't render for a bit after I'd suspect there are other files (images, javascript, css, etc) that are holding up the page from rending in the browser and not the html in the page
Page rendering . at this stage, view state for the page and all controls are saved. The page calls the Render method for each control and the output of rendering is written to the OutputStream class of the Page's Response property.
I have a large excel document that is generated when the user clicks on the download link. When the download link is clicked the browser pops up the standard open save cancel dialog. The problem is that the wait time can be really long e.g. 15 seconds or more before the dialog appears. I want to show a busy gif while the request is in progress. How can I accomplish this?
I'm pretty sure I can show a gif easily using jQuery, but I'm not sure how to stop/hide the busy indicator when the new document (excel doc) has finished loading. Is there a javascript event that I could attach a handler to?
Another option is the temporary file method: Is there a way to detect the start of a download in JavaScript?
Basically:
User clicks on download link/button
An AJAX request is sent to create the excel doc. Show the 'busy' indicator.
The excel doc is created and saved to a temporary file on the server. A response is sent containing a unique id that identifies the file.
The AJAX response is handled on the client-side. Hide the 'busy' indicator. window.location is changed to something like 'download.aspx?id=###' which prompts the user to save the file.
The problem here is that clicking the link fires off another request which is nothing to do with the first one. You could have the code that handles the download request update some kind of session data, which a bit of Ajax on the linking page then polls to determine when the request handler is in the process of offering up the data for download.
Alternatively, you could simply make it time out after a reasonable period of time, say 30 seconds, and perhaps offer up an explanation. This might then transition through a couple of states:
"Click here to download the super-duper PDF of awesomeness!"
"Please wait, generating a whole dollop of fonty goodness..."
"It may take some time to bundle all that uber-data into a download...if nothing's happening, maybe you want to try again?"
This seems to be the approach Google Mail takes when it comes to detecting timeouts or similar problems.