+2004-05-05 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * HttpSessionState.cs: added Clone (), which makes and exact copy but
+ with a cloned SessionDictionary. When EnableSessionState is set to
+ ReadOnly, we can modify the collection, but changes are not propagated.
+
+ * ISessionHandler.cs: changed signature of UpdateContext().
+
+ * SessionDictionary.cs: added Clone.
+
+ * SessionInProcHandler.cs:
+ * SessionSQLServerHandler.cs:
+ * SessionStateServerHandler.cs: don't create a new session if the handler
+ do not require it. UpdateContext() now returns an HttpSessionState to
+ the module.
+
+ * SessionStateModule.cs: removed IsReadOnly as it is now passed as a
+ parameter to the session handler. If the session is read-only, clone
+ it so that it can be changed but changes are not kept.
+
+ In short, we don't create session objects when not required and we
+ honor the ReadOnly sessions.
+
2004-02-09 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* SessionInProcHandler.cs:
_isReadonly = isReadonly;
}
+ internal HttpSessionState Clone ()
+ {
+ return new HttpSessionState (_id, _dict.Clone (), _staticObjects, _timeout, _newSession,
+ _isCookieless, _mode, _isReadonly);
+
+ }
+
public int CodePage {
get {
HttpContext current = HttpContext.Current;
{
internal interface ISessionHandler
{
- void Dispose ();
- void Init (HttpApplication context, SessionConfig config);
- bool UpdateContext (HttpContext context, SessionStateModule module);
- void UpdateHandler (HttpContext context, SessionStateModule module);
+ void Dispose ();
+ void Init (HttpApplication context, SessionConfig config);
+ HttpSessionState UpdateContext (HttpContext context, SessionStateModule module, bool required,
+ bool read_only, ref bool isNew);
+
+ void UpdateHandler (HttpContext context, SessionStateModule module);
}
}
{
}
+ internal SessionDictionary Clone ()
+ {
+ SessionDictionary sess = new SessionDictionary ();
+ int last = sess.Count;
+ for (int i = 0; i < last; i++) {
+ string key = GetKey (i);
+ sess [key] = this [key];
+ }
+
+ return sess;
+ }
+
internal void Clear ()
{
_dirty = true;
}
//this is the code that actually do stuff.
- public bool UpdateContext (HttpContext context, SessionStateModule module)
+ public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+ bool required, bool read_only, ref bool isNew)
{
SessionContainer container = null;
string id = SessionId.Lookup (context.Request, config.CookieLess);
container = (SessionContainer) _sessionTable [id];
// if we have a session, and it is not expired, set isNew to false and return it.
- if (container!=null && container.SessionState!=null && !container.SessionState.IsAbandoned) {
- // Can we do this? It feels safe, but what do I know.
- container.SessionState.SetNewSession (false);
+ if (container != null && container.SessionState != null &&
+ !container.SessionState.IsAbandoned) {
+ if (required)
+ container.SessionState.SetNewSession (false);
// update the timestamp.
container.Touch ();
- // Can we do this? It feels safe, but what do I know.
- context.SetSession (container.SessionState);
- return false; // and we're done
- } else if(container!=null) {
+ if (required)
+ return container.SessionState;
+
+ return null;
+ } else if (container!=null) {
_sessionTable.Remove (id);
}
}
+ if (!required)
+ return null;
+
// else we create a new session.
string sessionID = SessionId.Create (module.Rng);
- container = new SessionContainer (new HttpSessionState (sessionID, // unique identifier
- new SessionDictionary(), // dictionary
- HttpApplicationFactory.ApplicationState.SessionObjects,
- SESSION_LIFETIME, //lifetime befor death.
- true, //new session
- false, // is cookieless
- SessionStateMode.InProc,
- module.IsReadOnly)); //readonly
- // puts it in the table.
+ HttpSessionState state = new HttpSessionState (sessionID, // unique identifier
+ new SessionDictionary(), // dictionary
+ HttpApplicationFactory.ApplicationState.SessionObjects,
+ SESSION_LIFETIME, //lifetime before death.
+ true, //new session
+ false, // is cookieless
+ SessionStateMode.InProc,
+ read_only); //readonly
+
+ container = new SessionContainer (state);
_sessionTable [sessionID]=container;
AppDomain.CurrentDomain.SetData (".MonoSessionInProc", _sessionTable);
-
- // and returns it.
- context.SetSession (container.SessionState);
- context.Session.SetNewSession (true);
-
- // And we're done!
- return true;
+ isNew = true;
+ return container.SessionState;
}
}
}
public void UpdateHandler (HttpContext context, SessionStateModule module)
{
- if (context.Session == null)
+ if (context.Session == null || context.Session.IsReadOnly)
return;
string id = context.Session.SessionID;
UpdateSession (id, dict);
}
- public bool UpdateContext (HttpContext context, SessionStateModule module)
+ public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+ bool required, bool read_only, ref bool isNew)
{
+ if (!required)
+ return null;
+
HttpSessionState session = null;
string id = SessionId.Lookup (context.Request, config.CookieLess);
if (id != null) {
- session = SelectSession (id, module.IsReadOnly);
- if (session != null) {
- context.SetSession (session);
- return false;
- }
+ session = SelectSession (id, read_only);
+ if (session != null)
+ return session;
}
id = SessionId.Create (module.Rng);
session = new HttpSessionState (id, new SessionDictionary (),
- HttpApplicationFactory.ApplicationState.SessionObjects, config.Timeout, true,
- config.CookieLess, SessionStateMode.SQLServer, module.IsReadOnly);
+ HttpApplicationFactory.ApplicationState.SessionObjects, config.Timeout,
+ true, config.CookieLess, SessionStateMode.SQLServer, read_only);
InsertSession (session, config.Timeout);
- context.SetSession (session);
-
- return true;
+ isNew = true;
+ return session;
}
private void GetConnectionData (out string providerAssembly,
namespace System.Web.SessionState
{
- [MonoTODO]
public sealed class SessionStateModule : IHttpModule
{
internal static readonly string CookieName = "ASPSESSION";
static SessionConfig config;
static Type handlerType;
ISessionHandler handler;
- bool read_only;
private RandomNumberGenerator rng;
get { return rng; }
}
- internal bool IsReadOnly
- {
- get { return read_only; }
- }
-
public void Dispose ()
{
if (handler!=null)
handler.Dispose();
}
- [MonoTODO]
public void Init (HttpApplication app)
{
if (config == null) {
HttpApplication application = (HttpApplication) o;
HttpContext context = application.Context;
- read_only = (context.Handler is IReadOnlySessionState);
+ bool required = (context.Handler is IRequiresSessionState);
+ bool read_only = (context.Handler is IReadOnlySessionState);
bool isNew = false;
+ HttpSessionState session = null;
if (handler != null)
- isNew = handler.UpdateContext (context, this);
-
- if (isNew && config.CookieLess) {
- string id = context.Session.SessionID;
- context.Request.SetHeader (HeaderName, id);
- context.Response.Redirect (UrlUtils.InsertSessionId (id,
- context.Request.FilePath));
- } else if (isNew) {
- string id = context.Session.SessionID;
- HttpCookie cookie = new HttpCookie (CookieName, id);
- cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
- context.Response.AppendCookie (cookie);
+ session = handler.UpdateContext (context, this, required, read_only, ref isNew);
+
+ if (session != null) {
+ if (isNew)
+ session.SetNewSession (true);
+
+ if (read_only)
+ session = session.Clone ();
+
+ context.SetSession (session);
+
+ if (isNew && config.CookieLess) {
+ string id = context.Session.SessionID;
+ context.Request.SetHeader (HeaderName, id);
+ context.Response.Redirect (UrlUtils.InsertSessionId (id,
+ context.Request.FilePath));
+ } else if (isNew) {
+ string id = context.Session.SessionID;
+ HttpCookie cookie = new HttpCookie (CookieName, id);
+ cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
+ context.Response.AppendCookie (cookie);
+ }
}
// In the future, we might want to move the Async stuff down to
public void UpdateHandler (HttpContext context, SessionStateModule module)
{
- if (context.Session == null)
+ if (context.Session == null || context.Session.IsReadOnly)
return;
string id = context.Session.SessionID;
state_server.Update (id, dict.ToByteArray (), sobjs.ToByteArray ());
}
- public bool UpdateContext (HttpContext context, SessionStateModule module)
+ public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+ bool required, bool read_only, ref bool isNew)
{
+ if (!required)
+ return null;
+
StateServerItem item = null;
HttpSessionState session = null;
SessionDictionary dict = null;
if (item != null) {
dict = SessionDictionary.FromByteArray (item.DictionaryData);
sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData);
- session = new HttpSessionState (id, dict, HttpApplicationFactory.ApplicationState.SessionObjects,
+ session = new HttpSessionState (id, dict,
+ HttpApplicationFactory.ApplicationState.SessionObjects,
config.Timeout, false, config.CookieLess,
- SessionStateMode.StateServer, module.IsReadOnly);
- context.SetSession (session);
- return false;
+ SessionStateMode.StateServer, read_only);
+
+ return session;
}
}
state_server.Insert (id, item);
- session = new HttpSessionState (id, dict, sobjs, config.Timeout,
- true, config.CookieLess, SessionStateMode.StateServer, module.IsReadOnly);
-
- context.SetSession (session);
+ session = new HttpSessionState (id, dict, sobjs, config.Timeout, true,
+ config.CookieLess, SessionStateMode.StateServer,
+ read_only);
- return true;
+ isNew = true;
+ return session;
}
private string GetId (HttpContext context)