Redirecting to a slow aspx page - asp.net

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.

Related

ASP.NET 4.0 Ajax Progress Bar Options

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!

Cross-page posting with target _blank leaves source page unfunctional

I'm trying to describe it in as few steps as possible:
I have Page1.aspx with lot of controls, and Preview and Save button among those. I also have Page2.aspx that is the redirection target of a Preview Button click.
Since I need all the controls selections from Page1 to draw a preview on Page2 the redirection is done with setting Preview's PostBackUrl.
I also must have preview shown on a new tab or window so I used onClientClick="aspnetForm.target='_blank'" for Preview button definition.
Save button-click callback, after storing data to a database does redirection to some Page0.aspx (initial list of reports - the subject of the code)
Preview button works fine - a preview renders in a new tab, but when I go to the old tab and click on Save, I see from debugger, that firstly Page2.aspx(?) and secondly Page1.aspx are loaded. Then all the data is stored in the db, but though Page0 redirection is executed Page1.aspx stays loaded in the browser.
I have no idea what processes are behind this. Could one who knows give me an insight? Or if you consider my approach impossible to implement give some idea how to do the same?
If it's of importance, everything on the Page1 is located in an update panel.
Thank you very much for replying
In ASP.NET there are basically zero (0) circumstances in which you will ever send form data from one page to another. Although what exactly you are trying to accomplish is vague, you can consider some of the following:
Isolate unique operations/systems to a single page. If you have something like a User Profile, don't have three different aspx pages; just use a single page for the user or admin to manage that data / functions. Postback events are your friend.
Understand the difference between ViewState and traditional form data. I'm guessing that if you're trying to post form data from one page to another, you probably don't understand the point of ViewState. Using a single page to maintain temporary data that the user is currently working with is a great use for ViewState. If you want the data to appear on another page then you need to consider the data from the previous page as final and thus should be saved to a database or some other medium.
These are just some general guidelines because there is no exact answer to your problem without saying something generic like "You're doing it wrong." I would recommend starting by never again trying to post form data from one aspx page to another.

Asp.net output cache substitution with postback in user control

We have a site where all pages are output cached, i.e. the caching is on aspx-level with VaryByParam="*". Now there is a requirement to make a gallup control, i.e. a small "How is this site working for you?" and then when the user clicks an answer the results are shown.
The gallup is implemented as a usercontrol that is added to the master page so gallups can be added to any page to which a gallup is created in the cms. The problem is that output cache naturally caches all clicks so when user no 2 votes he sees the results that where calculated after the first vote on that alternative.
Now I'm trying to use cache substition. I added an asp:Substition tag where the user control used to be, load the control dynamically and render it (using this approach http://coderwall.com/p/4ajzqq). The problem is that the postbacks that voting triggers is never fired. Apparently the method that the substition control executes is loaded outside the page life cycle or too late.
Any ideas?
Regards,
Mathias
I solved this by skipping the substitution control and just used the user control as normal, so the gallup/question view was output cached. Then in the click handler for the answer alternatives I added
Response.Cache.SetNoServerCaching();
which exempted the results view from output cache and hence it was updated as it should.
It is also possible to use Response.Cache.SetNoServerCaching() in Global.asax, using VaryByCustom. It merely requires sensing in Global.asax whether the page is a post-back or not. Here is a code example.

triggering javascript events using asp.net

I'm writing an asp.net web app. and i've hit a bit of a brick wall.
basically i have 2 pages, the main page with a text box in and a popup that contains a treeview.
My problem is this. when i select a treeview item i want the program to perform some database transactions using asp.net and then pass the value retrieved from the database into a javascript function that passes the data back from the popup page to the parent page. My problem is that i cannot find any way of calling a javascript function from asp.net. I've tried assigning attributes to controls on page load, but this does not work as when the page loads the data has not been retrieved from the database.
Have a look at the ClientScriptManager class. You can register scripts from code-behind that will run when the HTML page loads. Those scripts can call other javascript functions on the page.
There are many tutorials and examples on the Web. Here's one I found that may help but there are many more.
How to use the client script manager
You hit the nail on the head when you said "I've tried assigning attributes to controls on page load, but this does not work as when the page loads the data has not been retrieved from the database." You just need to discover when you're pulling the data from the database, and then assign the values after that. Without looking at your code, there's no way to know for sure, but Page_PreRender is probably a good bet to assign your values...it's probably after you're pulling information from the db...it's pretty much the last place that you can make things happen before the html is generated for the client.
You can invoke a function resided in the Main Page and call that function in the Main Page from the Child Page which is your pop up window.
Please refer to these links for references
http://chiragrdarji.wordpress.com/2007/03/10/call-parent-windows-javascript-function-from-child-window-or-passing-data-from-child-window-to-parent-window-in-javascript/
http://www.webmasterworld.com/forum91/2957.htm
http://hspinfo.wordpress.com/2008/01/12/call-parent-windows-javascript-function-from-child-window/
This one helps with retrieving popups from values using javascript
http://www.eggheadcafe.com/articles/20060117.asp
This one shows how to fire a postback using javascript, and manage it in the codebehind.
http://weblogs.asp.net/mnolton/archive/2003/06/04/8260.aspx
If you put them together, and use Control.ClientID to find the actual "html name" of your asp.net controls, you'll be able to set that up in no time.
Might not be the prettiest way to do it in town, and incidentally make little baby Jesus cry, but anyway, it works.
[edit]Oh. I just saw that it seems I answered the question the other way around, or "how to trigger codebehind from Javascript". I think the method I suggest may help you, if you use it right.
The javascript of the popup should pass the information to the parent window, and the parent window function should call a postback when it receives the information.
The javascript of the popup window should be only registered on a postback with the correct information retrieved, so that when the postback occurs on the popup because of the selection of the right information, the window closes and passes the information to the parent page.
The parent page, triggering postback, does the thingies you need it to, and the app resumes "normally" from there on, doing whatever you need it to, outside of the popup page.

Please wait dialog & downloading files in asp.net

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.

Resources