Tuesday, 3 May 2011

MongoDB ASP.NET Session State Store Provider

Please note: v1.1.0 of this Sesssion State Provider is now available. See blog post: http://www.adathedev.co.uk/2013/03/mongodb-aspnet-session-store-provider.html
I've pushed up an initial drop of a custom ASP.NET session state store, backed by MongoDB, to my GitHub repository. After a quick test it seems OK, though could do with a real hammering before being deemed production worthy! So if you want to use it, just make sure you give it a good test through and most importantly, let me know how it goes! It's based on the sample custom session state provider in this MSDN article, basically just with the MongoDB specific bits swapped in.

Session state is stored in a "Sessions" collection within a "SessionState" database. Example session document:
{
    "_id" : "bh54lskss4ycwpreet21dr1h",
    "ApplicationName" : "/",
    "Created" : ISODate("2011-04-29T21:41:41.953Z"),
    "Expires" : ISODate("2011-04-29T22:01:41.953Z"),
    "LockDate" : ISODate("2011-04-29T21:42:02.016Z"),
    "LockId" : 1,
    "Timeout" : 20,
    "Locked" : true,
    "SessionItems" : "AQAAAP////8EVGVzdAgAAAABBkFkcmlhbg==",
    "Flags" : 0
}

Inline with the MSDN reference ("ODBCSessionStateStore" changed appropriately to "MongoSessionStateStore"):
If the provider encounters an exception when working with the data source, it writes the details of the exception to the Application Event Log instead of returning the exception to the ASP.NET application. This is done as a security measure to avoid private information about the data source from being exposed in the ASP.NET application.

The sample provider specifies an event Source property value of "MongoSessionStateStore". Before your ASP.NET application will be able to write to the Application Event Log successfully, you will need to create the following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MongoSessionStateStore

If you do not want the sample provider to write exceptions to the event log, then you can set the custom writeExceptionsToEventLog attribute to false in the Web.config file.

The session-state store provider does not provide support for the Session_OnEnd event, it does not automatically clean up expired session-item data. You should have a job to periodically delete expired session information from the data store where Expires date is in the past, i.e.:
db.Sessions.remove({"Expires" : {$lt : new Date() }})

Example web.config settings
<configuration>
  <connectionStrings>
    <add name="MongoSessionServices" connectionString="mongodb://localhost" />
  </connectionStrings>
  <system.web>
    <sessionState
        mode="Custom"
        customProvider="MongoSessionStateProvider">
      <providers>
        <add name="MongoSessionStateProvider"
             type="MongoSessionStateStore.MongoSessionStateStore"
             connectionStringName="MongoSessionServices"
             writeExceptionsToEventLog="false"
             fsync="false"
             replicasToWrite="0" />
      </providers>
    </sessionState>
  </system.web>
</configuration>

A few points to note, to give some control over fault tolerance and consistency:
  • if you want updates to the MongoDB store to be fsync'd before returning, set fsync="true"
  • if you have a replica set and want updates to be persisted to multiple nodes before returning, set the replicatesToWrite setting to the appropriate number.
SafeMode is currently always enabled.

If you give a whirl, please let me know how you get on.