I'm experimenting with creating a crude, proof-of-concept session state store provider in ASP.Net. But I've got a problem and I'm not sure what to do about it. The website works properly when using the InProc provider. The Session_Start in global.asax is called on session creation as it should. But not if I implement my own provider. The Session_Start method from global.asax isn't being called at all if a new session is being created (that is, I delete the session state file).
Am I missing something important here?
public class TestSessionProvider : SessionStateStoreProviderBase
{
private const string ROOT = "c:\\projects\\sessions\\";
private const int TIMEOUT_MINUTES = 30;
public string ApplicationName
{
get { return HostingEnvironment.ApplicationVirtualPath; }
}
private string GetFilename(string id)
{
string filename = String.Format("{0}_{1}.session", ApplicationName, id);
char[] invalids = Path.GetInvalidPathChars();
for (int i = 0; i < invalids.Length; i++)
{
filename = filename.Replace(invalids[i], '_');
}
return Path.Combine(ROOT, Path.GetFileName(filename));
}
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
throw new ArgumentNullException("config");
if (String.IsNullOrEmpty(name))
name = "Sporkalicious";
base.Initialize(name, config);
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
SessionStateItemCollection items = new SessionStateItemCollection();
HttpStaticObjectsCollection objects = SessionStateUtility.GetSessionStaticObjects(context);
return new SessionStateStoreData(items, objects, TIMEOUT_MINUTES);
}
/// <summary>
/// The CreateUninitializedItem method is used with cookieless sessions when the regenerateExpiredSessionId
/// attribute is set to true, which causes SessionStateModule to generate a new SessionID value when an
/// expired session ID is encountered.
/// </summary>
/// <param name="context"></param>
/// <param name="id"></param>
/// <param name="timeout"></param>
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
FileStream fs = File.Open(GetFilename(id), FileMode.CreateNew, FileAccess.Write, FileShare.None);
BinaryWriter writer = new BinaryWriter(fs);
SessionStateItemCollection coll = new SessionStateItemCollection();
coll.Serialize(writer);
fs.Flush();
fs.Close();
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
return GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
locked = false;
lockAge = TimeSpan.FromDays(1);
lockId = 0;
actions = SessionStateActions.None;
if (!File.Exists(GetFilename(id)))
{
return null;
}
FileStream fs = File.Open(GetFilename(id), FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
BinaryReader reader = new BinaryReader(fs);
SessionStateItemCollection coll = SessionStateItemCollection.Deserialize(reader);
fs.Close();
return new SessionStateStoreData(coll, new HttpStaticObjectsCollection(), TIMEOUT_MINUTES);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
File.Delete(GetFilename(id));
}
public override void ResetItemTimeout(HttpContext context, string id)
{
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
if (!File.Exists(GetFilename(id)))
{
CreateUninitializedItem(context, id, 10);
}
FileStream fs = File.Open(GetFilename(id), FileMode.Truncate, FileAccess.Write, FileShare.None);
BinaryWriter writer = new BinaryWriter(fs);
SessionStateItemCollection coll = (SessionStateItemCollection)item.Items;
coll.Serialize(writer);
fs.Flush();
fs.Close();
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return false;
}
public override void InitializeRequest(HttpContext context){}
public override void EndRequest(HttpContext context){}
public override void Dispose(){}
}