Friday, June 3, 2011

Type-Safe ASP.NET Session

I just hate loosing object types such as you do in when retreving objects from the ASP.NET session, like done here


// Fails if the key does exists in the session
// as an integer cannot be null
int id = (int)Session["id"];
// Doesn't throw an error as we handle null
int id = Session["id"] == null ? -1 : (int)Session["id"];
Wouldn’t it be nice if we handled this more gracfully? And actually  got the object back we expected? This could easily be accomplished using extension methods.

public static class SessionExtensions
{
    public static T Get<T>(this HttpSessionStateBase session, string key)
    {
        return (T)session[key];
    }

    public static bool TryGet<T>(this HttpSessionStateBase session, string key, out T item)
    {
        object sessionItem = session[key];
        if (sessionItem == null)
        {
            item = default(T);
            return false;
        }

        try
        {
            item = (T)sessionItem;
        }
        catch (InvalidCastException)
        {
            item = default(T);
            return false;
        }

        return true;
    }

    public static Result<T> SafeGet<T>(this HttpSessionStateBase session, string key)
    {
        object sessionObject = session[key];
        if (sessionObject == null)
        {
            return new Result<T> { Success = false };
        }

        try
        {
            T item = (T)sessionObject;
            return new Result<T> { Success = true, Value = item };
        }
        catch (InvalidCastException)
        {
            return new Result<T> { Success = false };
        }
    }
}

public class Result<T>
{
    public T Value { get; set; }
    public bool Success { get; set; }
}

I’ve created several methods to get the value from session. The Get method just gets the object and casts it to the specified object, the downside here is the possibility for an InvalidCastException. The TryGet method, uses the standard .NET way, and uses and out parameter. The last method, SafeGet, is my prefered way (I just hate out parameters), and returns an object which contains the success and the value. Each method can be used like this


Session["test"] = 10;
int integer = Session.Get<int>("test");
if (Session.TryGet("test", out integer)) {
    // Use value
}
var resultObject = Session.SafeGet<int>("test");
if (resultObject.Success) {
        // Use value (result.Value)
}

This method can of course easily be adapted to similar situations like TempData.

No comments:

Post a Comment