How to capture session state - asp.net

I have a asp .net master page application and one content page has a number of controls on it.
I want to store the content/state of those controls in the session state whenever a user navigates to another content page.
My question is, how do I know when to capture the control state? Is there an event of some type I can use to trigger a procedure?
Thanks in advance for any info.
Bill

There aren't any real "global" server side event handlers that you can use to detect when the user is going to another page (or even just hitting the back button in the browser).
The best bet is to simply write a method in your master page that will save your session state and then execute a Response.Redirect() to the location specified. Then make all of your links go through this method when you need to track session state.

Presumably they are navigating away from that page via a control that you have provided them (button, link, etc.) You can trap the action on the server side at that point and cache your state.

What about using session variables?
See this link for more info:
ASP.Net Session
There's a number of ways to maintain state. There are trade-offs no matter which version you use. For example, I wouldn't use session variables on an app that is load-balanced across multiple servers; you're not guaranteed to get the same server for each request, and the state is stored on a server-by-server basis.
It's hard to beat this
Session["myState"] = 7; // bad example
for simplicity, though. :)

Related

how to prevent session abandonment for idle user (session wise)

I have a page on my web app where users might use for potentially hours with no server interaction. all interactions are done on the page with javascript.
how can I prevent a session abandonment if I do want to have it set for 20 minutes on all other pages?
my solution is sending an empty ajax call every 10 minutes just to tickle the server, but is there any other option?
You can make a dummy ajax call to renew the session timeout.
To do this, create an empty .aspx page, and use whatever you want to load that page to renew the session. For example, a JavaScript setInterval and a jquery $.get()
If you don't fill comfortable using JavaScript and jQuery, you always can use an Ajax Timer' and another AjaxUpdatePanel`.
This guarantees that the session will keep alive while the browser is open.
Making all sessions longer doesn't look like the best possible solution.
Dependign on where you need this functionality, you can implement it on a master page, or include it where needed. You can even include it in the masterpage and enable or disable the timer.
In ASP.Net, you can change Session.Timeout before returning to extend it on that page. I have not tested whether or not it would un-extend on other subsequent requests, but it would be worth looking at.
http://msdn.microsoft.com/en-us/library/ms524319(v=vs.90).aspx

Why is viewstate serialized to a hidden field in the form and not kept on the server?

I am quite new to WebForms and I'm trying to understand the ViewState. AFAIK today, it keeps modifications of the UI over postbacks to the same page. But why does it send the state (= stored modifications) to the client and does not keep it on the server saving CPU cycles and bandwidth?
Am I understanding something completely wrong?
The view state is something intrinsically connected to the view, as the name implies, and trying to manage it separately while maintaining that relation is not something that is easily accomplished.
You would need to store view state per page, so you would still have to send to the client an ID in order to be able to get the correct view state on a postback. Another serious issue is that you send a page to the client but you don't know when or if the client is going to postback that page to the server, so you would need to store view state at least until the session expires.
This could lead to a waste of server resources, as all those view states are being stored for users that may never postback to the server. If you keep your view state slim you'll agree that the best place to store it is to send it with view.
Finally, if you're still not happy with the view state on the client you can override the SavePageStateToPersistenceMedium and LoadPageStateFromPersistenceMedium methods of the page and save it to another medium. I've already heard many people complain about view state on the client, and most time I just tell them to go ahead and implement persistence to another medium on the server... however, I believe no one ever did, probably because it's complicated and you'll end up with a solution that's not that clean.
ViewState is used when a page performs a post back in order to restore the control tree of the page to what is was when the page was last rendered.
This allows for instance a GridView control to keep it's state (what is shown in the GridView) on post back without having to rebind it to the same data.
The reason why the ViewState per default is serialized and sent to the client is (I guess) that it's the easiest way to get it back when the client performs a post back.
What if for instance a user has several browser windows open with the same page loaded and you have the viewstate stored in the Session? Assigning the correct viewstate to the different windows in such a case can of course be solved, but having the client explicitly post it seems to be the easiest way.
That said, it is possible to have the viewstate stored in the Session. See for instance this link.
Other possibilities are available by implementing your own System.Web.UI.PageStatePersister.

ASP.NET feedback during long submit

This is probably a really simple thing. Basically, the user clicks a button and a potentially long running task happens. I'd like to do a few things like toggle the button's enabled state, show a spinner, etc. In VB.NET Winforms I'd just do Application.DoEvents() and the updates would happen and the code can continue. How can I do this in ASP.NET? (preferable serverside or minimal javascript)
There are a few ways to approach this in ASP.Net depending on exactly what your requirement is. Getting the process started is fairly easy, but monitoring it for completion from the client side will require more work in both the server and the client.
The basic outline of the solution is:
1) Perform some action on the client that initiates the action. For example, you could post the entire page back on a button click, initiate an ajax request, or have a partial page postback depending on how much information you need from the page.
2) On the server side, initiate the task using a BackgroundWorker, make an entry in a workflow queue, or store a request in a database table that is monitored by a service that is responsible for performing the action.
3) Back on the client side, use javascript start a window.timeout loop that, when it times out, issues an ajax request to the web server to check on the completion. Using a timeout loop like this will ensure that the UI remains responsive and that any animations being displayed will display correctly. How you check on the completion will depend on how your server-side implementation is designed, but will almost certainly require a database.
We use the following general approach for initiating reports from the web client, which can be long running:
When the user initiates the report, open a new window to the report generation page on the client using javascript, passing the page enough parameters to get it started. Opening a separate window allows the user to continue working, but still see that there is something happening.
The user interface for the report page basically contains an animated GIF so that the user knows that something is going on.
When the report page is initially loaded on the server, it generates a unique id for monitoring the status of the report and embeds this in javascript for use in monitoring the status. It then stores this unique identifier in a database table that contains the unique id and a status column, initializing the status to requested.
Once the database entry has been made, the page fires off a BackgroundWorker to initiate the action and then returns the page to the user.
When the page is displayed, javascript starts a window.timeout loop that periodically fires off an ajax request to the web server, which then checks the database for the status of the report using the unique identifier created earlier.
When the backgroundworker finishes the report, either successfully or in failure, it updates the database table with the status, location of the report or error messages and terminates.
When the javascript loop finds that the report generation has completed, it either displays the error message or the report to the user.
Hopefully, this gives you some ideas for solving your issue.
The issue with this could be that once the page is posting you can't update other sections of the page.
you can use multiple asp:updatepanel and communicate to other update panel's causing the state to change in the panel.
take a look at this link:
http://www.ajaxtutorials.com/ajax-tutorials/tutorials-using-multiple-updatepanels-in-net-3-5-and-vb/
it will show you how to accomplish this.

Is there a way using ASP.NET to always run some server side code when a user leaves a page?

I was wondering if there is any way to always run some server side code when a user leaves a page in ASP.NET. The page Unload event is no good because that doesn't get called if someone clicks on a link. Ideally I'd also like the code to run even if the user closes the browser.
I suspect what I'm asking isn't possible, but it doesn't hurt to ask
Problem is, HTTP is a stateless protocol, so when the page has finished being served, you wont know if the user is still on the page or not.
The only way to acheive this would be a hidden piece of Javascript that constantly pings the server with it's session ID, or another similar mechanism. When the ping becomes unresponsive you can reasonably assume the page is not being viewed by the user anymore.
Here is a diagram that explains traditional HTTP message flow.
im not really sure if you can do that but i have a workaround in mind.
There is an event in the DOM called onbeforeunload. it get calls everytime a user leaves a page. you can try sending an ajax request to the server from this function.
The closest thing you can come without creating too messy a solution is to enable ASP sessions. This will create a session on the server for each visitor, who will be identified by a cookie.
After a certain amount of inactivity from the visitor, the session will be closed, and a SessionEnd event will be raised. This you can hook up to in the Global.asax file.
I will not recommend this however, because HTTP is pr. definition a session-less protocol, and using server based sessions violates this fact, and are often problematic. Many solutions that use server based sessions run into problems when the user uses the browser-back button, and resubmits a form. Because the content of the submitted form no longer corresponds the data that exists in the server session.
Also, enabling server based sessions seriously hurts the scalability of the application.
Not that I know of. You'll need to use javascript for that, and call a web service on the server side.

Can a single asp.net user make more than one request at a time if the Session is in use?

I am not able to make more than one request at a time in asp.net while the session is active. Why does this limitation exist? Is there a way to work around it?
This issue can be demonstrated with a WebForms app with just 3 simple aspx pages (although the limitation still applies in asp.net mvc).
Create an asp.net 3.5 web application.
There should be just three pages:
NoWait.aspx, Wait.aspx, and SessionStart.aspx
NoWait.aspx has this single nugget added between the default div tags: <%=DateTime.Now.Ticks %>. The code-behind for this page is the default (empty).
Wait.aspx looks just like NoWait.aspx, but it has one line added to Page_Load in the code-behind: Thread.Sleep(3000); //wait 3 seconds
SessionStart.aspx also looks just like NoWait.aspx, but it has this single line in its code-behind: Session["Whatever"] = "Anything";
Open a browser and go to NoWait.aspx. It properly shows a number in the response, such as: "633937963004391610". Keep refreshing and it keeps changing the number. Great so far! Create a new tab in the same browser and go to Wait.aspx. It sits for 3 seconds, then writes the number to the response. Great so far! No, try this: Go to Wait.aspx and while it's spinning, quickly tab over to NoWait.aspx and refresh. Even while Wait.aspx is sleeping, NoWait.aspx WILL provide a response. Great so far. You can continue to refresh NoWait.aspx while Wait.aspx is spinning, and the server happily sends a response each time. This is the behavior I expect.
Now is where it gets weird.
In a 3rd tab, in the same browser, visit SessionStart.aspx. Next, tab over to Wait.aspx and refresh. While it's spinning, tab over to NoWait.aspx and refresh. NoWait.aspx will NOT send a response until Wait.aspx is done running!
This proves that while a session is active, you can't make concurrent requests with the same user. Requests are all queued up and served synchronously. I do not expect or understand this behavior. I have tested this on Visual Studio 2008's built in web server, and also IIS 7 and IIS 7.5.
So I have a few questions:
1) Am I correct that there is indeed a limitation here, or is my test above invalid because I am doing something wrong?
2) Is there a way to work around this limitation? In my web app, certain things take a long time to execute, and I would like users to be able to do things in other tabs while they wait of a big request to complete. Can I somehow configure the session to allow "dirty reads"? This could prevent it from being locked during the request?
3) Why does this limitation exist? I would like to gain a good understanding of why this limitation is necessary. I think I'd be a better developer if I knew!
Here is a link talking about session state and locking. It does perform and exclusive lock.
The easiest way around this is to make the long running tasks asynchronous. You can make the long running tasks run on a separate thread, or use and asynchronous delegate and return a response to the browser immediately. The client side page can send requests to the server to check and see if it is done (through ajax most likely), and when the server tells the client it's finished, notify the user. That way although the server requests have to be handled one at a time by the server, it doesn't look like that to the user.
This does have it's own set of problems, and you'll have to make sure that account for the HTTP context closing as that will dispose certain functionality in the asp.net session. One example you'll probably have to account for is probably releasing a lock on the session, if that is actually occurring.
This isn't too surprising that this could be a limitation. Each browser would have it's own session, before the advent of ajax, post back requests were synchronous. Making the same session handle concurrent could get really ugly, and I can see how that wouldn't be a priority for the IIS and ASP.NET teams to add in.
For reasons Kevin described, users can't access two pages that might write to their session state at the same time - the framework itself can't exert fine-grained control over the locking of the session store, so it has to lock it for entire requests.
To work around this, pages that only read session data can declare that they do so. ASP.NET won't obtain a session state write lock for them:
// Or false if it doesn't need access to session state at all
EnableSessionState="ReadOnly"

Resources