I have a website which uses Session.SessionID as a key, to lookup information about the user in my database (essentially managing state from page to page). I'm trying to make my site web-farmable and am having issues. It seems I can no longer user Session.SessionID to identify a user because it uses 'Session State' which is a no go on webfarm. I am aware that if the user has cookies turned on, it's all good, but I want users with cookies turned off to also be able to use my site.
What confuses me is when cookies are turned off and a user browses my site, the SessionID appears in the address bar. Why, if this information is being passed forward and backwards usin the URL, does it also need to rely on Session State?
Any answers or information links will be hugely appreciated!
SessionState is stored in the server's memory for as long as the session is active, or until your code removes values from it. The problem with this in a multi-server environment is that you are not guaranteed to get the same server with every request. Thus your Session data can be on server A while your current request is going to server B.
I'm not exactly sure of how this works in a multi-db environment (unless you have constant replication taking place), but you can store Session data in the database. You can also set up a server that is dedicated to storing state values.
MCP - Web Based Client Development .NET 2.0
Thanks for your reply. I'm trying to avoid storing Session State in the database for reasons i wont bother you with. Session.SessionID (e.g. a long string like "oz1fvv45ambj4zvxqgqky22x") is the only time I use Session State on my site, just to remember who a user is from page to page. In web.config I have <b>cookieless="AutoDetect"</b> which means normally this SessionID is stored in a cookie. However when cookies are not allowed by the user, this funny long string (SessionID) appears in the URL. I ignorantly thought that when a webfarm came along I could replace the Session.SessionID syntax with some code to grab this value from the URL (if cookies are off), but the problem is since it's part of session state, when the user goes to a different webserver in the farm and the previous Session State is obviously not there, a new one of these SessionID's is issued in the URL. Even though a valid SessionID was in the URL when requesting the page.
I'm starting to think I might be forced to store session state in the database. Or write my own code which, if cookies are turned off, appends this value to the Querystring for every page request (manually pass it around myself).
any thoughts appreciated.
Yes, you would have to code your own "ID" mechanism. You would need to implement something that checks in the incoming request querystring for a specific key. If it doesn't exist, then you generate a unique id and tack it on. Then, you also need to make sure you persist that querystring value in all the links and such on your site. For example, if you're menu's navigate url is "/home.aspx", the querystring would be erased. So either make sure you build all links to include your ID in the querystring or implement something that filters the response and adds it to every link.
As to your question about the session id in the url...
Think of the session as a hash table of hash tables. The first hash table is a collection of all the different session states for the application and is keyed off the session id. Using that key, ASP.NET now has a reference for the specific client's session - which is basically just another hash table keyed off whatever you add (e.g. Session["customerID"] = xyz;).
The session id is not stored in the session as a session item, it's stored on the client (as a cookie or persisted in the url) and set in the session class's SessionID property for easy reference.
I do think the easiest solution would be to store the session externally so your web-farm shares that first "hash table". Even though you only need it to keep track of the current client, the implementation of persisting the session id is already in place.
Also, I seem to remember something about if you don't actually use the session for anything, a new one is created on every request. So store something stupid like the current date (do this in global.asax for the session start event).
Thanks js, you've explained it well. your mention of "The session id is not stored in the session as a session item, it's stored on the client (as a cookie or persisted in the url) and set in the session class's SessionID property for easy reference." is what I originally thought.
However I find it bizzare that when you go to a different webserver in a web farm it ditches the Session ID from your URL and gives you a new one. Do you believe this is correct? To be honest I don't have a webfarm setup yet, I am testing this by manually changing the domain and using two different webservers. So in a real webfarm what I am saying might be wrong?
Two different webservers will have two different hash tables.
The first request to server 1 will get a session id, which is added to server 1's hash table.
The second request to server 2 will get a new session id because that other session id is not in server 2's hash table.
A web farm doesn't share memory (the inprocess session) - so each server in the farm would have a different hash table. This is why you need a common storage mechanism for the session like sql server.
I don't have any experience with web farms, I'm just making logical observations.
Ok thanks, I understand what you're saying and it backs up my tests and new understanding. I guess I was generalising my terms, maybe a more appropriate title for this thread is "Session.SessionID, if it uses In Process Memory, why also persist it in the URL?". I still think it is silly to have something rely on In Process Memory when it's already being passed up and down in the URL, but maybe Microsoft have their reasons.
timmortlock:"Session.SessionID, if it uses In Process Memory, why also persist it in the URL?".
I think you are forgetting the stateless (disconnected) nature of the web.
When you request a page, a connection is made to the server, downloads the page, and closes the connection.
When you click a link on that page, another connection is made to the server, but the server has no way to know that it came from the same browser window that made the last request. It knows that it came from the same IP, but it could be a different window. It doesn't know that it's the same browser window.
By passing the same session id with every request, the server can now associate all requests with the same browser window.
On the very first request, no session id is sent. This indicates to the server that a new session is starting. The server will then generate a new unique session id and pass it back to the browser window so that all further requests from that browser window can send that session id. The server keeps a database (of sorts) of all the sessions that it has started. When a request comes in that has a session id, it does a lookup of that id and loads the appropriate information. If that id is not found, it starts a new session, generates a new session id and passes that back to the browser window.
We, as developers, can specify where that database is kept. By default it is kept in the server's memory. In this case, server B does not have access to server A's memory, and so any sessions ids generated from server A will not exist on server B and so server B will generate a new id.
We can configure the servers to keep the database in a more central location - like sql server - so that they can share the same session database. Now, the session id generated by server A can be passed to server B and server B will use the same session that server A created.
sorry, it's hard to get my question across in writing. i do understand the stateless nature of web. the crux for me is in your quote. I had hoped this session id concept was simply a method for creating a tracking id (either in cookie or url), no looking up of details in memory like 'session state'.jshepler:When a request comes in that has a session id, it does a lookup of that id and loads the appropriate information. If that id is not found, it starts a new session, generates a new session id and passes that back to the browser window.
Even so, it would work for me if it did this: "If that id is not found, it starts a new session using that id. Of course there's the instance of no id being passed in the URL (e.g. browsing for the first time) in which it would need to generate a new session id".
Thanks for your replies. You've helped me understand that the asp.net session id concept is not going to work for me. I will need to store the server memory in SQL or code my own session id concept