How do I keep TCP/IP socket open in IIS? - asp.net

I have the following use scenario: User logs in to ASP.NET application; and at some point makes a connection to remote TCP/IP server. The server's response may come after significant delay (say, a few hours). Imagine that the user submits a batch job, and the job may be running for a long time. So, the user may close the browser, get some coffee and come back to see the results later.
However, if client closes the connection, the server will never return the results. So, keeping Socket info in Application object won't work - once user closes the browser, it goes away.
Is there any other way to persist this open socket while IIS is up? Also, if the second user logs in, I would prefer to use the same connection. Finally, I realize that the solution is brittle, and it may occasionally break. It's OK.
Remote server is 20-year old mainframe application; so no chance for changes there. And as long as the user doesn't log out - everything is working fine now. Everything is on the LAN, so there are no routing issues to complicate the situation.

The contents of the application dictionary are not lost when a user logs out. Your scheme will work (in a brittle way, but you say that's ok).
Note, that worker processes can exit for many reasons, so expect to be killed at arbitrary points in time.

you have several options for persisting session-state: MSDN - Session-State Modes
inproc mode: you disconnect, state is lost. if you use cookies, and
store info/data somewhere on the backend, then you can map the GUID
to the data, regardless of session. or use application-state.
stateserver: persisted across disconnects and application restarts,
but not across iis/pool/server restarts, unless you use another
server, or cookie/auth. can be problematic sometimes.
sqlserver: as the name implies, uses a specially formatted db/table structure to persist state data across all sorts of scenarios.
custom/off: allows you to build your own provider, or turns it off completely.
here's the cookie method, by far the simplest (you have to generate a GUID, then store it in the cookie and application state or a backend DB): MSDN - Maintaining Session State with Cookies
you can persist cookies on the user's client. then, on server
reboot/client disconnect/any other scenario just pull the GUID from
app/session state or from a backend DB, which will also store the data
for the reports/output.
also, as a caution: even though cookies can be used to auth a user to an account/db record via GUID, it is considered insecure for all other purposes except unindentifiable information, such as: view shopping cart, simple reports, status, etc...
oh, and the stuff on IIS session timeouts (20 mins by default): MSDN - Configure Session Time-out (IIS 7) and MSDN - Configure Idle Time-out Settings for an Application Pool (IIS 7)
completely forgot to add the links on: ASP.NET Application State Overview, ASP.NET Session State Overview, but storing large amounts of data on a busy server in application state is not recommended. oh yea, and MSDN - Caching Application Data

Related

what will happen after browser closing

We know that when we closed the browser, session gets destroy.
Please help me with below query.
Lets say i have clicked on submit button on my registration page and internally it get called SQL store procedure, which takes more time to execute..
on same time if i closed the browse what will happen?
Does my sql connection still available ? if yes then after closing browser still my store procedure is in execute mode?
when exactly the session get destroy?
Would like to know more about this life cycle , Thanks
First have this in mind.
The session is connected with a cookie on the users browser.
The session have a time out.
If anything of this two gone, the session is gone, so let see them analytically.
Cookie
If the cookie is a session cookie (temporary), then is gone when the user close the browser, if its not temporary then is gone when it expires, or of course if the user clears it, or if the user is in private mode is not even saved.
So when the cookie that is connected with the session is gone, you lose the session
The session can be lost even if the browser is not been able to read the session cookie for other reasons.
Session Data on server
The session that is connected with the cookie, is a Dictionary of data that lives on server.
The session have a timeout, so if the user did not update the call to the server inside this time, the server kills the session data on server.
Also, note that the session can be served on the SQL Server, or in a service that runs on background and keeps that data in memory.
If you save the session data on the memory, then they can be lost even before the session times out, from IIS recycle, from the service itself that clears it for their reasons.
Server Side Time Out
If you call a long time function, and the users ends their connection, then the procedure will be continue to runs until either ends either gets a time out. This is not so safe if your process takes 10 minute to execute, you probably gets timeout and never ends correct, even if the user is still connected. If you talk for few seconds, then its relative ok, the procedure will executed even if the users close his browser side.
Check the time out of the page and the time out of the sql server side. If you end well with the user connected, you will end the same and if the user close their connection in the middle.
Have in mind that in a heavy multi user call situation you may have a problem from the session locks, read this q/a ASP.NET Server does not process pages asynchronously
So take care the procedure to not take more than few seconds.
Last words
The most "secure way" to not lost your session in a time period is to use well setup cookie, that is not temporary and keep their life for some months (google keeps their cookie for two years), and use SQL Server to saves your session data.
More details to read at:
ASP.NET State Management Recommendations
Session would not retain values and always return null
Keeping a related ASP.NET application's session alive from another ASP.NET application
ASP.NET Session State Overview

Why is ViewState not stored on the server by default?

Can someone give me a good reason why ViewState isn't stored on the server by default?
Why not send a small session token in place of ViewState, which can then be mapped to whatever ViewState info is needed on the server, to prevent the whole ViewState being posted back and forwards multiple times.
Am I missing something?
Scalability - imagine how much server resources would be needed if a complex WebForms page was viewed by 1M users. Server would need to hold ViewState for at least the duration of the session timeout. Automatic server side cleanup of viewstate would also be problematic - user may be viewing several pages at once so ViewState for all pages would need to be retained.
Edit
There are several techniques discussed in these posts on how to move viewstate to the server. However, before you do that, it would be a good idea to remove unnecessary viewstate from controls / pages which don't need it (e.g. View only / no postback rendering).
I'm guessing now, but when viewstate was designed 10 years or so ago, 1GB RAM on a 32 bit server was about as good as it got, and MS presumably had to think of hosting providers wanting load 100's of apps per server. So bandwidth was probably viewed as cheaper than server Ram and disk storage.
There are a number of issues with storing the ViewState in memory.
If the application recycles, the VS for all anyone using the application is lost.
It increases the memory consumption of the application. This isn't an issue if there are only a few apps hosted on a server; but there are cases when there could be many websites hosted on one box.
Scalability; the more active the application, the more VS needs to be stored. And you can't assume 1-1 (1 user - 1 VS). A user can have multiple tabs open, can go back, leave tabs inactive, etc... which leads to:
How long do you store VS? Keeping the data encoded on the page ensures that it'll still be there if the user leaves the site open for a while.
What happens if you're hosted on a web farm. We can't guarantee that the user will hit the same machine on each request.
That being said, there are a few solutions:
Memcached-Viewstate - stores the VS in distributed memory using Memcache. This isn't ideal - if a server goes down the VS for anyone who had the VS stored to that server is lost, but will allow for application pools to reset without issue.
SQL-Viewstate - stores the VS in a SQL database. This adds a least 1 DB read and 1 DB write per request. Again, not ideal, but if the VS is getting unmanagable getting and setting the VS from the database is faster than sending and recieving it over HTTP.
Filesystem-Viewstate - stores the VS in the filesystem. It's less expensive than the SQL connection but would require a file server to work in a distributed environment.
It improves scalability because the server doesn't need to maintain all of that in memory. It is possible to store the viewstate in session but it's generally not recommended.
The root cause is using client side view state is that server doesn't know the current state of the page.
If a user is anxious, does multiple (partial) postback on the page, without waiting the response, browser will send out multiple partial postback requests, that each request create a new view state on server side, which will eventually flush out the initial view state in the browser. Finally the user does his last postback, at that time, the inital copy is gone, thus exception is thrown.
Also server side view state impacts server performance and user experience. If a user doesn't interact with the page for a day or a long time, the view state on server will expire. When the user posts back the page later, an exception is thrown.
For instance I watch youtube video of length 40 minutes. Yesterday I watched the first half, didn't close the tab but hiberated my computer. Today I continue watchig the last half, and post back something, the page will get errored out if the view state is in server and expired.

ASP.net Session in SQL or cookie

I deployed an ASP.net web site to two servers and put them behind the load balanced environment. Now that problem is that the performance is really slow. Even for just simple button event, it takes long time to finish the simple button event. However, if I access the site separately (by its server’s address), performance is good. What our system engineer told me was that the application handles session state in process as if it runs on only one server, it could not handle clustering. So, he suggested that I should use the session object in the code to store the session in SQL server, or cookie.
I am currently using session variables to store the session.
I am kind of a new to ASP.net and I am not sure exactly what this mean and how I can accomplish this in my .net code (C#)?
Thanks.
Here is a good link to start you off: ASP.NET Session State
You would probably want to go with the Out of process mode where the servers all access 1 session process on a designated server, if speed is your top priority or SQL Server mode where all servers access 1 database if reliability is your top priority as with out of process mode if the process dies your session data is lost similar to how in-process session handling works.
No coding changes for storing session data would be needed, just the initial configuration of the environment and a web.config change.
First off, you need to configure sessionstate in your web.config for what you want to do. Here is a step by step tutorial on storing sessionstate in sql server. Hope it helps!
http://support.microsoft.com/kb/317604

Basic: How is the session id created?

Does IIS create the session id when a request is received and where is that saved (client or server)?
How does server recognize that the request is coming from the same user/session?
The answer to your first question is Yes -- if sessions are used, and Both.
A cookie is a short bit of text passed back and forth between client and server with every request/response.
IIS generates a session id, saves it, and any associated data, and passes the in a cookie to the client (browser).
When the client makes another request, it sends the cookie, containing the sessionID back to the server. The server can then look at the cookie and find the session (and the associated data) which is saved on the server.
In ASP.net, there are multiple places for the session to be saved, but it's always within the server infrastructure.
The default is the memory of the IIS Process. This means: if you reset IIS (or the whole PC) or even just the application pool within IIS, all sessions are deleted, and the session data is lost forever. Also, if you have a LOT of sessions and store a lot of data in each session, the process will require a lot of memory, which can be a problem. This is called "In-Proc" Sessions.
The main alternative is a SQL Server Database. That way, sessions are kept even after a restart and it does not really matter how large each session is. The main downside is the added latency: Fetching data from a database is slower that the In-Proc solution of course.
There are also some other methods how to store sessions (including the option to write a completely new session provider), but the two common ones are "The Memory of the Server" and "A MS SQL Database".

asp.net, stateserver, NLB, session lost

1st post on stackoverflow, hope to have great feedback :)
I'm currently trying to load balance our web site. We have set up a 2 cluster NLB on windows server 2003 with IIS 6.
While testing the setup, I found that sometimes, our session is lost. A day and a half later, here's the result:
Yes, our machine.config both have the same encryption/decryption key.
Yes, the id in iis metabase.xml are the same for both machine. Actually, the entire file are the same, except for "AdminACL".
Both web application are set with "StateServer" and both pointing at the same machine.
From that point, searching on google gives less information and possible solutions.
From what I know, there's no particular pattern that cause this problem. It just happen once in a while.
While trying to find the problem, I've seen that a request sent the asp session id cookie to the server, but the server didn't map it to the user session.
So the request number x was sent from the client, with the cookie, session was mapped, and everything went smoothly.
The request number x+1 was sent from the client, with the cookie, but session was not found.
Both request were made on the same machine in the NLB.
Here's a snippet of the asp trace.axd:
1st request:
Request Details
Session Id: j2ffvy45updpc52uhw1mbg55 Request Type: GET
Time of Request: 11/26/2008 2:58:06 PM Status Code: 200
Request Encoding: Unicode (UTF-8) Response Encoding: Unicode (UTF-8)
Request Cookies Collection
Name Value Size
ASP.NET_SessionId j2ffvy45updpc52uhw1mbg55 42
AID 22 9
Response Cookies Collection
Name Value Size
Headers Collection
Name Value
Cookie ASP.NET_SessionId=j2ffvy45updpc52uhw1mbg55; AID=22
2nd Request:
Request Details
Session Id: Request Type: POST
Time of Request: 11/26/2008 2:58:08 PM Status Code:
Request Encoding: Unicode (UTF-8) Response Encoding:
Request Cookies Collection
Name Value Size
Response Cookies Collection
Name Value Size
Headers Collection
Name Value
Cookie ASP.NET_SessionId=j2ffvy45updpc52uhw1mbg55; AID=22
As you can see in the 2nd request, the cookie is sent from the client, but asp seems to never add the cookies in it's "Request Cookies Collection". I think that's why it doesn't find the session.
So why the cookie is not mapped to the session? Is that the problem? Is the problem elsewhere?
Feel free to ask any clarifications.
Thank you all for your feedback.
JF
I finally found the answer to my problem. It's origin are within the application code (like 99% of a programmer's 3rd party tools 'bugs'). I decided to post it anyway in case someone is in a similar scenario.
This code was part of WebServiceRequester class. The web service requester class was instanciated when session was created and it is saved in session. During creation, we initalizate the member 'm_webServiceURL', and this member is saved in session after. At which value was this member initialize was depending on a setting on the local machine.
The important part is the following:
WebServiceRequester class contains a WebService objects.
WebService objects can't be saved in session, they are not serializable in asp. The property had the [NonSerialized] attribute on it. So everytime we accessed the 'WebService' property of the object for the first during a page life cycle, we had to create a new one, and assigning ot it the url 'm_webServiceURL' which was saved in session.
So you see, new webservice object, on possibly a different machine, meaning a different setting on each machine.
so here's what happened:
box 29 was set to access Web Service at localhost
box 30 was set to access Web Service as 192.168.253.29.
Technically, they are both set on the same machine. But here's a scenario:
login on box 29. m_webServiceURL is set to localhost in session.
[some request on box 29 here]
NLB balancing bring us on box 30.
box 30 loads it's session, create a new webservice obect with localhost as the web service address.
box 30 made the request to the wrong web service leading to a Session Expired exception.
One of the problem during the debug, was that the local communication were not recorded with the network monitor.
What lead me on the trace, was that we never had an exception logged on the box 29 log trace, as it should have.
Thanks for you suggestions everyone, it was really appreciated.
Have a good day.
JF
Not strictly an answer to your question, but have you tried it using a sql server based session store? (Search on MSDN for the permanent script rather than the temp script that's provided with asp.net)
I've heard "bad things" about the executable session service, and consequently have not used it. Never had any problems web farming with the sql server based solution though.
Sorry it's not strictly an answer to your problem, but it should either (a) fix it, or (b) narrow it down significantly.
Well, if you're using visual studio, you could at least test it with the MSDE (the cut down version of SQL Server that comes with Visual Studio)...
It might help rule out state server problems...
Using the database approach has its own issues. I think you should be able to use your preferred approach.
Perhaps this session troubleshooting article would help?
Or "Troubleshooting Session Related Issues in ASP.NET"
Or "Troubleshooting Expired ASP.NET Session State and Your Options"
I'll be lame and re-iterate the proposal of MS SQL Server. Install SQL Server Express which is completeley free including for commercial use and it has only these 3 drawbacks which shouldn't be a problem for you in this stage :
Max 4GB size database
Max 1 CPU Core used
Max 1GB RAM used
A few points to take into consideration:
What's the load on your website? State Server has the tendency to crash when facing a large number of concurrent hits. We're only using it in scenarios where we have a really small number of users (in the 10's, mostly backend systems). Whenever we tried using it in production for sites serving 1000's of users daily, it would crash leading to loss of session data.
On one of the production environments we manage, we're using MSSQL 2005 Express to manage the sessions, the site has 10K+ users a day and 200K+ pages a day. This is a recommended approach in case session is a must and tightly coupled into your application.
If you're about to user MSSQL Express as your state DB, remember that it doesn't come with SQL Server Agent meaning there's no tasks scheduler running in the background and cleaning your expired sessions. I'd recommend finding a scheduler and running the clean expired sessions stored procedure periodically.
Good luck
Instead of messing around with SQL, send your tests directly into one of your IIS nodes to see if you still get the same issue. I'm sure if your only doing a small number of tests StateServer won't be the issue.
Try setting the domain name of the asp.net_sessionid through code to ".yourdomain.com".
By default the ASP.net_SessionID cookie domain name is set to the full application path. So, this may be one of the reason why the cookie is not travelling.
E.g.
Request.Cookies["ASP.NET_SessionId"].Domain = ".yourdomain.com".
Remember the first "." is important in the domain name.
You could do this in the HttpModule in the AcquireRequestState event.

Resources