* HttpSessionState.cs: Make the SessionDictionary accessable
authorJackson Harper <jackson@novell.com>
Mon, 3 Nov 2003 21:08:59 +0000 (21:08 -0000)
committerJackson Harper <jackson@novell.com>
Mon, 3 Nov 2003 21:08:59 +0000 (21:08 -0000)
* ISessionHandler.cs: Add method to update the session state
data in the handler. Pass the session config to handlers when
initializing.
* SessionConfig.cs: Add StateNetworkTimeout
* SessionInProcHandler.cs: Updates because interface has
changed, all functionality is the same.
* SessionStateModule.cs: Get new config items, allow SQLServer
session manager type. Update session handlers when the session
state has been released.
* SessionStateSectionHandler.cs: Add StateNetworkTimeout
* SessionSQLServerHandler.cs: New class allows sessions to be
stored in a database.

svn path=/trunk/mcs/; revision=19596

mcs/class/System.Web/System.Web.SessionState/ChangeLog
mcs/class/System.Web/System.Web.SessionState/HttpSessionState.cs
mcs/class/System.Web/System.Web.SessionState/ISessionHandler.cs
mcs/class/System.Web/System.Web.SessionState/SessionConfig.cs
mcs/class/System.Web/System.Web.SessionState/SessionInProcHandler.cs
mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web.SessionState/SessionStateModule.cs
mcs/class/System.Web/System.Web.SessionState/SessionStateSectionHandler.cs

index 659ceeab4427f2de0b65504ebc5d1645b951e4c2..ed0e004048020e91258084a986faf31c6f6611b0 100644 (file)
@@ -1,3 +1,19 @@
+2003-11-03 Jackson Harper <jackson@ximian.com>
+
+       * HttpSessionState.cs: Make the SessionDictionary accessable
+       * ISessionHandler.cs: Add method to update the session state
+       data in the handler. Pass the session config to handlers when
+       initializing.
+       * SessionConfig.cs: Add StateNetworkTimeout
+       * SessionInProcHandler.cs: Updates because interface has
+       changed, all functionality is the same.
+       * SessionStateModule.cs: Get new config items, allow SQLServer
+       session manager type. Update session handlers when the session
+       state has been released.
+       * SessionStateSectionHandler.cs: Add StateNetworkTimeout
+       * SessionSQLServerHandler.cs: New class allows sessions to be
+       stored in a database.
+       
 2003-10-28 Jackson Harper <jackson@ximian.com>
 
        * HttpSessionState.cs: Do not allow timeout to be set to less then
index 8a419dcbc4e27c1bff5428c85a286f04ef98c315..65a847d683856ead4c8bcdb2534ec2e4ab98e1bd 100644 (file)
@@ -135,6 +135,10 @@ public sealed class HttpSessionState : ICollection, IEnumerable
                 }
        }
 
+       internal SessionDictionary SessionDictionary {
+               get { return _dict; }
+       }
+
        public void Abandon ()
        {
                _abandoned = true;
index 467144a9d22485b154a0b1330c304e3e60c73865..5e7b903646e72dbeb14b31227bedd01632390eff 100644 (file)
@@ -13,8 +13,9 @@ namespace System.Web.SessionState
        internal interface ISessionHandler
        {
              void Dispose ();
-             void Init (HttpApplication context);
+             void Init (HttpApplication context, SessionConfig config);
              bool UpdateContext (HttpContext context);
+             void UpdateHandler (HttpContext context);
        }
 }
 
index d5f660f117bf355d7e729e5b4dfab643e4df4bf5..22b138b3f814ef318907ffc9a5b36b114e53b6a8 100644 (file)
@@ -18,6 +18,7 @@ namespace System.Web.SessionState
                internal bool CookieLess;
                internal string StateConnectionString;
                internal string SqlConnectionString;
+               internal string StateNetworkTimeout;
 
                public SessionConfig (object parent)
                {
@@ -80,6 +81,11 @@ namespace System.Web.SessionState
                {
                        SqlConnectionString = value;
                }
+
+               internal void SetStateNetworkTimeout (string value)
+               {
+                       StateNetworkTimeout = value;
+               }
        }
 }
 
index 0d57460692cd1baeb0388c5925403bda2da191a1..0973a92ae59495a982d1f20bd1e54b6cdae50f95 100644 (file)
@@ -65,11 +65,14 @@ namespace System.Web.SessionState
                        _sessionTable = null;
                }
 
-               public void Init (HttpApplication context)
+               public void Init (HttpApplication context, SessionConfig config)
                {
                        _sessionTable = new Hashtable();
                }
 
+               public void UpdateHandler (HttpContext context)
+               {
+               }
 
                //this is the code that actually do stuff.
                public bool UpdateContext (HttpContext context)
diff --git a/mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs b/mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs
new file mode 100644 (file)
index 0000000..64cd269
--- /dev/null
@@ -0,0 +1,254 @@
+//
+// System.Web.SessionState.SessionSQLServerHandler
+//
+// Author(s):
+//  Jackson Harper (jackson@ximian.com)
+//
+// (C) 2003 Novell, Inc. (http://www.novell.com), All rights reserved
+//
+
+using System;
+using System.IO;
+using System.Data;
+using System.Reflection;
+using System.Configuration;
+using System.Collections.Specialized;
+
+namespace System.Web.SessionState {
+
+       internal class SessionSQLServerHandler : ISessionHandler
+       {
+               const string CookieName = "ASPSESSION";
+               const int DefTimeout = 600;
+
+               private Type cncType = null;
+               private IDbConnection cnc = null;
+               private SessionConfig config;
+
+               public void Dispose ()
+               {
+                       if (cnc != null) {
+                               cnc.Close ();
+                               cnc = null;
+                       }
+               }
+
+               public void Init (HttpApplication context, SessionConfig config)
+               {
+                       string connectionTypeName;
+                       string providerAssemblyName;
+                       string cncString;
+
+                       this.config = config;
+
+                       GetConnectionData (out providerAssemblyName, out connectionTypeName, out cncString);
+                       if (cncType == null) {
+                               Assembly dbAssembly = Assembly.Load (providerAssemblyName);
+                               cncType = dbAssembly.GetType (connectionTypeName, true);
+                               if (!typeof (IDbConnection).IsAssignableFrom (cncType))
+                                       throw new ApplicationException ("The type '" + cncType +
+                                                       "' does not implement IDB Connection.\n" +
+                                                       "Check 'DbConnectionType' in server.exe.config.");
+                       }
+
+                       cnc = (IDbConnection) Activator.CreateInstance (cncType);
+                       cnc.ConnectionString = cncString;
+                       try {
+                               cnc.Open ();
+                       } catch (Exception exc) {
+                               cnc = null;
+                               throw exc;
+                       }
+               }
+
+               public void UpdateHandler (HttpContext context)
+               {
+                       if (context.Session == null)
+                               return;
+
+                       string id = context.Session.SessionID;
+                       SessionDictionary dict = context.Session.SessionDictionary;
+
+                       UpdateSession (id, dict);
+               }
+
+               public bool UpdateContext (HttpContext context)
+               {
+                       HttpSessionState session = null;
+                       string id = GetId (context);
+
+                       if (id != null) {
+                               session = SelectSession (id);
+                               if (session != null) {
+                                       context.SetSession (session);
+                                       return false;
+                               }
+                       }
+
+                       id = System.Guid.NewGuid ().ToString ();
+                       session = new HttpSessionState (id, new SessionDictionary (),
+                                       new HttpStaticObjectsCollection (), config.Timeout, true,
+                                       false, SessionStateMode.SQLServer, false);
+
+                       InsertSession (session, config.Timeout);
+                       context.SetSession (session);
+                       context.Session.IsNewSession = true;
+                       context.Response.AppendCookie (new HttpCookie (CookieName, id));
+
+                       return true;
+               }
+
+               private void GetConnectionData (out string providerAssembly,
+                               out string cncTypeName, out string cncString)
+               {
+                       providerAssembly = null;
+                       cncTypeName = null;
+                       cncString = null;
+
+                       NameValueCollection config = ConfigurationSettings.AppSettings as NameValueCollection;
+                       if (config != null) {
+                               foreach (string s in config.Keys) {
+                                       if (0 == String.Compare ("StateDBProviderAssembly", s, true)) {
+                                               providerAssembly = config [s];
+                                       } else if (0 == String.Compare ("StateDBConnectionType", s, true)) {
+                                               cncTypeName = config [s];
+                                       }
+                               }
+                       }
+
+                       cncString = this.config.SqlConnectionString;
+
+                       if (providerAssembly == null || providerAssembly == String.Empty)
+                               providerAssembly = "Npgsql.dll";
+
+                       if (cncTypeName == null || cncTypeName == String.Empty)
+                               cncTypeName = "Npgsql.NpgsqlConnection";
+
+                       if (cncString == null || cncString == String.Empty)
+                               cncString = "SERVER=127.0.0.1;USER ID=monostate;PASSWORD=monostate;dbname=monostate";
+               }
+
+               private HttpSessionState SelectSession (string id)
+               {
+                       HttpSessionState session = null;
+                       IDbCommand command = cnc.CreateCommand();
+                       IDataReader reader;
+
+                       string select = "SELECT * from aspstatetempsessions WHERE SessionID = :SessionID";
+
+                       command.CommandText = select;
+
+                       command.Parameters.Add (CreateParam (command, DbType.String, ":SessionID", id));
+
+                       try {
+                               reader = command.ExecuteReader ();
+
+                               if (!reader.Read ())
+                                       return null;
+
+                               SessionDictionary dict = null;
+                               MemoryStream stream = null;
+                               int len = (int) reader.GetBytes (reader.FieldCount-1, 0, null, 0, 0);
+                               byte[] data = new byte[len];
+                               reader.GetBytes (reader.FieldCount-1, 0, data, 0, len);
+                               try {
+                                       stream = new MemoryStream (data);
+                                       dict = SessionDictionary.Deserialize (new BinaryReader (stream));
+                               } catch {
+                                       throw;
+                               } finally {
+                                       if (stream != null)
+                                               stream.Close ();
+                               }
+
+                               session = new HttpSessionState (id, dict,
+                                               new HttpStaticObjectsCollection (),
+                                               100, true, false,
+                                               SessionStateMode.SQLServer, false);
+                               return session;
+                       } catch {
+                               throw;
+                       }
+
+               }
+
+               private void InsertSession (HttpSessionState session, int timeout)
+               {
+                       IDbCommand command = cnc.CreateCommand ();
+                       IDataParameterCollection param;
+
+                       string insert = "INSERT INTO ASPStateTempSessions VALUES " +
+                       "(:SessionID, :Created, :Expires, :Timeout, :SessionData)";
+
+                       command.CommandText = insert;
+
+                       param = command.Parameters;
+                       param.Add (CreateParam (command, DbType.String, ":SessionID", session.SessionID));
+                       param.Add (CreateParam (command, DbType.DateTime, ":Created", DateTime.Now));
+                       param.Add (CreateParam (command, DbType.DateTime, ":Expires", Tommorow ()));
+                       param.Add (CreateParam (command, DbType.Int32, ":Timeout", timeout));
+                       param.Add (CreateParam (command, DbType.Binary, ":SessionData",
+                                                  GetDictData (session.SessionDictionary)));
+
+                       command.ExecuteNonQuery ();
+               }
+
+               private void UpdateSession (string id, SessionDictionary dict)
+               {
+                       IDbCommand command = cnc.CreateCommand ();
+                       IDataParameterCollection param;
+
+                       string update = "UPDATE ASPStateTempSessions SET " +
+                       "SessionData = :SessionData WHERE SessionId = :SessionID";
+
+                       command.CommandText = update;
+
+                       param = command.Parameters;
+                       param.Add (CreateParam (command, DbType.String, ":SessionID", id));
+                       param.Add (CreateParam (command, DbType.Binary, ":SessionData",
+                                                               GetDictData (dict)));
+
+                       command.ExecuteNonQuery ();
+               }
+
+               private IDataParameter CreateParam (IDbCommand command, DbType type,
+                               string name, object value)
+               {
+                       IDataParameter result = command.CreateParameter ();
+                       result.DbType = type;
+                       result.ParameterName = name;
+                       result.Value = value;
+                       return result;
+               }
+
+               private byte[] GetDictData (SessionDictionary dict)
+               {
+                       MemoryStream stream = null;
+                       try {
+                               stream = new MemoryStream ();
+                               dict.Serialize (new BinaryWriter (stream));
+                               return stream.GetBuffer ();
+                       } catch {
+                               throw;
+                       } finally {
+                               if (stream != null)
+                                       stream.Close ();
+                       }
+               }
+
+               private DateTime Tommorow ()
+               {
+                       return DateTime.Now.AddDays (1);
+               }
+
+               private string GetId (HttpContext context)
+               {
+                       if (!config.CookieLess &&
+                                       context.Request.Cookies [CookieName] != null)
+                               return context.Request.Cookies [CookieName].Value;
+
+                       return null;
+               }
+       }
+}
+
index 44bb0bddf9ca11725d5e6b7cb1deece1fea9d852..4696f6899e176eb56c460f9445c335df5c5bcd27 100644 (file)
@@ -37,15 +37,16 @@ namespace System.Web.SessionState
                                if (config ==  null)
                                        config = new SessionConfig (null);
 
-                               if (config.Mode == SessionStateMode.StateServer ||
-                                   config.Mode == SessionStateMode.SQLServer)
-                                       throw new NotSupportedException ("Only Off and InProc modes supported.");
+                               if (config.Mode == SessionStateMode.StateServer)
+                                       throw new NotSupportedException ("StateServer mode is not supported.");
+
+                               if (config.Mode == SessionStateMode.SQLServer)
+                                       handlerType = typeof (SessionSQLServerHandler);
                                
                                if (config.Mode == SessionStateMode.InProc)
                                        handlerType = typeof (SessionInProcHandler);
                        }
                                
-
                        app.AddOnAcquireRequestStateAsync (
                                new BeginEventHandler (OnBeginAcquireState),
                                new EndEventHandler (OnEndAcquireState));
@@ -55,12 +56,18 @@ namespace System.Web.SessionState
                        
                        if (handlerType != null && handler == null) {
                                handler = (ISessionHandler) Activator.CreateInstance (handlerType);
-                               handler.Init(app); //initialize
+                               handler.Init(app, config); //initialize
                        }
                }
 
                void OnReleaseRequestState (object o, EventArgs args)
                {
+                       if (handler == null)
+                               return;
+
+                       HttpApplication application = (HttpApplication) o;
+                       HttpContext context = application.Context;
+                       handler.UpdateHandler (context);
                }
 
                void OnEndRequest (object o, EventArgs args)
index be3c843e7a3db7e94ead7ca875310be357da2ed7..b5c5042285985fc77cca198aa93650eb7b58c590 100644 (file)
@@ -48,6 +48,10 @@ namespace System.Web.SessionState
                        if (attvalue != null)
                                config.SetSqlConnectionString (attvalue);
 
+                        attvalue = AttValue ("stateNetworkTimeout", section);
+                        if (attvalue != null)
+                                config.SetStateNetworkTimeout (attvalue);
+
                        if (section.Attributes != null && section.Attributes.Count > 0)
                                HandlersUtil.ThrowException ("Unknown attribute.", section);