Grax Coding

Tuesday, June 11, 2013

Simple Strongly-Typed pattern for ViewData, Session, Request, etc

Here is a simple pattern for setting up strongly-typed but flexible access to your ViewData, Session, and Request variables.

If you have worked with jQuery much, you are familiar with the pattern of using "SomeMethod(value)" to set a value and "SomeMethod()" to get the value back.  What we are going to do is create extension methods on ViewData, Session, or Request to set and/or get strongly typed data.
  1. Add a new class titled "ObjectDictionaryExtensions" (or whatever you want to call it) 
  2. Add a static modifier to the ObjectDictionaryExtensions class
    • "public static class ObjectDictionaryExtensions"
Add a ViewData "property" by adding the following methods
public static ViewDataDictionary FirstName(this ViewDataDictionary collection, string value)
{
    collection["FirstName"] = value;
    return collection;
}

public static string FirstName(this ViewDataDictionary collection)
{
    return collection["FirstName"] as string;
}

Add a Session "property" by adding the following methods

public static HttpSessionState FirstName(this HttpSessionState collection, string value)
{
    collection["FirstName"] = value;
    return collection;
}

public static string FirstName(this HttpSessionState collection)
{
    return collection["FirstName"] as string;
}

Add a Request "property" by adding the following method. Note that the Request collection is read-only

public static string FirstName(this HttpRequest collection)
{
    return collection["FirstName"];
}

Accessing these methods looks like this

ViewState.FirstName("Jason");
var firstName = ViewState.FirstName();

Session.FirstName("Johnny");
var firstName = Session.FirstName();

var firstName = Request.FirstName();

Namespaces

If your extension methods are not in the same namespace as the code that will be using them, you will either need to put a "using (namespace of extension method static class)" on every page you plan to use it, or change the namespace of your extension method static class to be the same as the other pages.  This will enable Intellisense and make the extension methods very easy to use.

To add the equivalent of a global using statement to your Razor views, edit your Views/web.config file.
Locate the key "/configuration/system.web.webPages.razor/pages/namespaces"
and add your own namespace by adding an element that looks like <add namespace="DefaultNamespace.Extensions" />

Selecting a Key

In the examples, I use "FirstName" as the key.  However, your key (at least with the ViewState and Session objects) can be anything you like, as long as you use the same key in the getter and the setter.  You can reduce the chance of name collisions with other parts of your application by selecting something more complex or obscure for the key.

Value types

For non-nullable types, be sure to handle the situation where the item is not found in the collection.  One solution is to return a default value (preferably "default(type)") when the item is not found.  The other solution is to return a Nullable<type> that returns the value when found, else null.