Asked by:
IIS 6.0 Session Timeout Vs Web.Config Timeout Vs App pool Idle time out

Question
-
User769474054 posted
I want to increase the session timing of my ASP.NET web App hosted in IIS 6.0. So, I changed the SessionState timing to 600 mins in web.config of the site. But it didn't work and my session times out like in an hour.(
Session["myVariable"] == null
)<system.web> <sessionState timeout="600" /> </system.web>
Now I tried setting the Timeout value in IIS website where this application is hosted by going to website -> Properties -> Home Directory Tab -> Configuration button -> Options tab and changin it to 600 mins, still no luck. The question here says that this is for classic ASP Pages but not for ASP.NET web sites. which means that I am doing it wrong.
Then I checked the app pool under which this application runs (app Pool->Properties-->Performance tab). This says "Recycle Worker Process(in minutes)" as 10 mins. I read many questions on SO but none of them gives a clear cut answer on how to increase the session timeout on ASP.NET WebApp.
I want to know the difference between these three settings and when to use which and how do we increase the session timeout of my webApp.
I know I can use other session state methods like StateServer and SQL Server but It could be quite laborious for me to change the way each session variable is accessed. More over Session_End method doesn't fire in StateServer mode which Ia m using for some resource cleaning.
So, overall i am looking to extend the session time to 600 mins with INPROC session mode which is not working. Any pointers on that and help me understand the best option possible
Wednesday, January 24, 2018 10:08 PM
All replies
-
User1120430333 posted
SessionState timing to 600 minutes? Oh my! :)
You are joking, right?
What's the purpose of this even if you could it?
Thursday, January 25, 2018 4:31 AM -
User-1838255255 posted
Hi Pavanlalit,
According to your description, as far as i know, you set the sessiontimeout to 600 minutes, this setting maybe block the concurrent of the application pool, so i suggest you could adjust the application pool idle time out value, it is should as same as you need session time.
Best Regards,
Eric DuThursday, January 25, 2018 9:41 AM -
User769474054 posted
This is a request System where user enters info by verifying another sheet which obviously takes time. In the code behing,we are using sessoin variables to store some of the info and save it to DB. Since the user takes easily >20 mins, and sometimes hours in entering info on the page, we decided to extend the session to avoid the errors in code behind as I said. Thus we agreed upon 10 hours as theworst case time and when trying to update the session time correspondingly, I am still getting timeout well before than 1 hour.
Thursday, January 25, 2018 8:00 PM -
User769474054 posted
Hi Eric,
Yes, I set the sesiontimeout to 600 mins in web.config of the site. But I get the session timed out way earlier than that. So, wondering where else do I need to change and found out that apppool idle time out could be the culprit. So, just posting it here to get the confirmation and other potential things I might be missing or a better idea to do this.
So, as per your answer, I just need to set the app pool idle time out right? can you explain a bit on the differnces between setting in web.config, app pool idle time out and IIS6.0 Session time out?
Thursday, January 25, 2018 8:04 PM -
User475983607 posted
Rather than persisting data in server memory (Session) save the data in database table.
Thursday, January 25, 2018 8:50 PM -
User769474054 posted
RIght, thats certainly the option, but I want to know the pain of changing the implementation of this techniques as I am using INPROC. Since this is a huge application and we are using session variables in many locations, I want to see if its worth the effort.
Thursday, January 25, 2018 8:57 PM -
User1120430333 posted
RIght, thats certainly the option, but I want to know the pain of changing the implementation of this techniques as I am using INPROC. Since this is a huge application and we are using session variables in many locations, I want to see if its worth the effort.
What you need to do is come up with logic that xml serializes a graph of custom objects to hold the session data and save to DB table per user session. The graph is kept in session and saved to the database per user session on Page Unload on an async thread. The object graph is put back into session if there is a timeout. But as long as a user had a page open with the page or pages having hidden unique key information, then the data for a user can be pulled from the Session table, and the object graph put back into session. The user can walk away from the workstation with the browser open on a page walk away for a month, but has long as the browser is not closed on the page, the user session can be put back into session from the data pulled from the database as if no session timeout ever occurred.
I have done the above.
Friday, January 26, 2018 5:41 AM -
User769474054 posted
Hi DA924,
Thanks for the reply. Do you have an example that I can use to start with or see how its done? I haven't done this and many articles say that there is a SQLState mode but none of them shows the usage of it in a real world example.
Friday, January 26, 2018 2:55 PM -
User1120430333 posted
I'll give you the breakdown on how the Community Of Practice (CoP) object was kept in state for a user using the application. The CoP object is a container object for all the DTO(s) Data Transfer Objects for certain Web pages and areas on a Web page. The public properties of a DTO were bound to the controls on a given page. So as the user moved to page to page, the CoP object was serialized and persisted to the State table every time the Page_Unload was done, which was done on a spawned async thread so that it wouldn't interfere with the responsiveness of the overall application's speed.
The key here is what is being called a Session-id. It is a GUID assigned to the user when the user logged into the application. Each page has a hidden field on the page to hold the GUID. The Session-id was obtained from the page, and the key was formulated to go after the last State record for the user in the State table anytime the CoP object was found not to be in session with the CoP object being a null value object due to session timeout. The retrieval of the CoP object for a user is based on the last known object for the user in the State table. The CoP object was deserialized and put back into session. Like I said, as long as a page was up in the browser and the machine was on after a session timeout, the last known CoP object in the State table for the user was retrieved and the CoP object put back into session as if there was no session timeout.
There was a little batch program that ran everyday to delete any State records that were like 30 days old or ran whenever needed as the State table had a lot records in it due the application was a high volume usage application.
The State record was no more than a composite-key with nvarchar of like 3,000 or something holding the XML serialized CoP with its DTO(s) in it.
I hope you get the jest of it which is no more than XML serialization and deserialization of an object persisted to the DB. Find out how to spawn an async thread to save he Cop object to State table. I couldn't find the code. It's a big project from year 2008, and I am tired of going down the rabbit hole trying to find that code on the backend.
HTH
protected override void OnInit(EventArgs e) { ModuleIsInCoP(enumModuleID.MOD_USER_ADMINISTRATION); GetMode(Request.QueryString["Mode"]); sessionguid = Request.QueryString["SG"]; SetSecurity(); CheckSession(); SetTabClickEvents(); #region Check the CoP Object var cop = new DTOCoP(); if (CoP != null) { cop = CoP; } else { if (Mode == CCMMode.Creation) { CurCoPID = 0; } else { CurCoPID = CoPID; } var _CoPPresenter = new CoPPresenter(this); CurUserID = UserID; CurSessionID = "COPCM" + sessionguid; _CoPPresenter.GetCoPStateObject(); cop = CoP; } #endregion hfCopDirty.Value = cop.IsCopOrChildDirty.ToString(); if (!Page.IsPostBack) { LoadValues(cop); } else { ReloadNeighborhoods(cop); } CheckTabs(cop); base.OnInit(e); } protected void Page_Load(object sender, EventArgs e) { ModuleIsInCoP(enumModuleID.MOD_USER_ADMINISTRATION); GetMode(Request.QueryString["Mode"]); SetSecurity(); CheckSession(); SetTabClickEvents(); ConfirmMode(Request.QueryString["Mode"]); if (Page.IsPostBack) ReloadNeighborhoods(CoP); if (Mode == CCMMode.Creation) LockDownTabs(CoP.CurrentTab); CheckTabs(CoP); } protected void Page_Unload(object sender, EventArgs e) { SaveCoPStateObject(); } #region Save CoP object to state table private void SaveCoPStateObject() { var _CoPPresenter = new CoPPresenter(this); CurUserID = UserID; CurSessionID = "COPCM" + sessionguid; _CoPPresenter.SaveCoPStateObject(); } #endregion #region Delete CoP objects from state table private void DeletCoPStateObjects(object aobj) { Int32 copid = CoP.ID; Session["CoPObj" + sessionguid] = null; if (Mode == CCMMode.Creation) copid = 0; mCommunityService.DeleteCoPStataObjects(UserID, "COPCM" + sessionguid, copid); } public void SaveCoPStateObject() { if (mView.CoP != null) { var client = new CommunityClient(); client.SaveCoPStateObject(mView.CurUserID, mView.CurSessionID, mView.CoP.ID, SerializeAnObject(mView.CoP)); client.Close(); } } public void GetCoPStateObject() { var client = new CommunityClient(); mView.CoP = DeSerializeAnObject(client.GetCoPStateObject(mView.CurUserID, mView.CurSessionID, mView.CurCoPID), typeof(DTOCoP)) as DTOCoP; client.Close(); } private static string SerializeAnObject(object AnObject) { var XmlDoc = new XmlDocument(); var Xml_Serializer = new XmlSerializer(AnObject.GetType()); var MemStream = new MemoryStream(); try { Xml_Serializer.Serialize(MemStream, AnObject); MemStream.Position = 0; XmlDoc.Load(MemStream); return XmlDoc.InnerXml; } finally { MemStream.Close(); } } private static Object DeSerializeAnObject(string XmlOfAnObject, Type ObjectType) { if (XmlOfAnObject == string.Empty) { var client = new CommunityClient(); var DTOCoP = Translate(client.GetNewCop()); DTOCoP.SessionID = "Redirect"; client.Close(); return DTOCoP; } var StrReader = new StringReader(XmlOfAnObject); var Xml_Serializer = new XmlSerializer(ObjectType); var XmlReader = new XmlTextReader(StrReader); try { Object AnObject = Xml_Serializer.Deserialize(XmlReader); return AnObject; } finally { XmlReader.Close(); StrReader.Close(); } } } using System; using System.Data.Objects; using System.Linq; using KN.Tiers.Community.DAL.Model; using System.Transactions; using System.Data.EntityClient; namespace KN.Tiers.Community.DAL { public class CoPObjectState { #region private methods private const string mwdb = "name=MainWebDBEntities1"; private static readonly Func<MainWebDBEntities1, int, string, int, IQueryable<CoP_ObjState>> compiledQueryCoPObjState = CompiledQuery.Compile((MainWebDBEntities1 ctx, int userid, string sessionid, int copid) => (from a in ctx.CoP_ObjState.Where(a => a.UserID == userid && a.SessionID == sessionid && a.CopID == copid) .OrderByDescending(a => a.TimeStamp) select a)); #endregion public static string GetCoPStateObject(Int32 userid, string sessionid, Int32 copid) { var strreturn = string.Empty; //set it to read uncommited var transactionOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }; //create the transaction scope, passing our options in using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) using (var conn = new EntityConnection(mwdb)) using (var db = new MainWebDBEntities1(conn)) try { var stateobjs = compiledQueryCoPObjState.Invoke(db, userid, sessionid, copid).ToList(); foreach (var stateobj in stateobjs) { strreturn = stateobj.CoP_Object; break; } transactionScope.Complete(); } finally { conn.Close(); } return strreturn; } public static void SaveCoPStateObject(Int32 userid, string sessionid, Int32 copid, string AnObject) { using (var conn = new EntityConnection(mwdb)) using (var db = new MainWebDBEntities1(conn)) try { var objstate = new CoP_ObjState { UserID = userid, SessionID = sessionid, CopID = copid, TimeStamp = DateTime.Now.AddSeconds(2).AddMilliseconds(100), CoP_Object = AnObject }; db.AddToCoP_ObjState(objstate); db.SaveChanges(); } finally { conn.Close(); } } public static void DeleteCoPStataObject(Int32 userid, string sessionid, Int32 copid) { using (var conn = new EntityConnection(mwdb)) using (var db = new MainWebDBEntities1(conn)) try { using (var scope = new TransactionScope()) { var stateobjs = compiledQueryCoPObjState.Invoke(db, userid, sessionid, copid).ToList(); foreach (var stateobj in stateobjs) { db.DeleteObject(stateobj); db.SaveChanges(); } scope.Complete(); } } finally { conn.Close(); } } } }
Saturday, January 27, 2018 5:29 AM