Explorar el Código

* 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.

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

Jackson Harper hace 22 años
padre
commit
804bccf91f

+ 16 - 0
mcs/class/System.Web/System.Web.SessionState/ChangeLog

@@ -1,3 +1,19 @@
+2003-11-03 Jackson Harper <[email protected]>
+
+	* 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 <[email protected]>
 
 	* HttpSessionState.cs: Do not allow timeout to be set to less then

+ 4 - 0
mcs/class/System.Web/System.Web.SessionState/HttpSessionState.cs

@@ -135,6 +135,10 @@ public sealed class HttpSessionState : ICollection, IEnumerable
                 }
 	}
 
+	internal SessionDictionary SessionDictionary {
+		get { return _dict; }
+	}
+
 	public void Abandon ()
 	{
 		_abandoned = true;

+ 2 - 1
mcs/class/System.Web/System.Web.SessionState/ISessionHandler.cs

@@ -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);
 	}
 }
 

+ 6 - 0
mcs/class/System.Web/System.Web.SessionState/SessionConfig.cs

@@ -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;
+		}
 	}
 }
 

+ 4 - 1
mcs/class/System.Web/System.Web.SessionState/SessionInProcHandler.cs

@@ -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)

+ 254 - 0
mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs

@@ -0,0 +1,254 @@
+//
+// System.Web.SessionState.SessionSQLServerHandler
+//
+// Author(s):
+//  Jackson Harper ([email protected])
+//
+// (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;
+		}
+	}
+}
+

+ 12 - 5
mcs/class/System.Web/System.Web.SessionState/SessionStateModule.cs

@@ -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)

+ 4 - 0
mcs/class/System.Web/System.Web.SessionState/SessionStateSectionHandler.cs

@@ -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);