Skip to content

Strongly Typing TempData in your MVC Application with Extension Methods

As I’ve stated before, and for those that know me, when working with C# I try to use the compiler as often as I can and keep things strongly typed.  When I started working in MVC, I didn’t like the fact that TempData was defined like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class TempDataDictionary : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
public class TempDataDictionary : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
public class TempDataDictionary : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable

While TempData and ViewData being potentially valuable things, <string, object>, really?

Here is how I get around that and use the compiler to my advantage with some simple extension methods:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public static class TempDataExtensions
{
public static T Get<T>(this TempDataDictionary tempData, string key)
{
if (tempData[key] is T)
{
var tempDataItem = (T)tempData[key];
return tempDataItem;
}
throw new InvalidCastException(string.Format("Temp Data does not contain type {0} for key {1}", typeof(T), key));
}
public static void Set<T>(this TempDataDictionary tempData, string key, T value)
{
tempData[key] = value;
}
}
public static class TempDataExtensions { public static T Get<T>(this TempDataDictionary tempData, string key) { if (tempData[key] is T) { var tempDataItem = (T)tempData[key]; return tempDataItem; } throw new InvalidCastException(string.Format("Temp Data does not contain type {0} for key {1}", typeof(T), key)); } public static void Set<T>(this TempDataDictionary tempData, string key, T value) { tempData[key] = value; } }
public static class TempDataExtensions
{
    public static T Get<T>(this TempDataDictionary tempData, string key)
    {
        if (tempData[key] is T)
        {
            var tempDataItem = (T)tempData[key];
            return tempDataItem;
        }
        throw new InvalidCastException(string.Format("Temp Data does not contain type {0} for key {1}", typeof(T), key));
    }
 
    public static void Set<T>(this TempDataDictionary tempData, string key, T value)
    {
        tempData[key] = value;
    }
}

So, in your controller, you can Set to TempData and Get from TempData like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public ActionResult Index()
{
TempData.Set("SomeObjectKey", new SomeObject());
TempData.Set("SomeBoolKey", true);
TempData.Set("SomeStringKey", "test");
TempData.Get<SomeObject>("SomeObjectKey"); // returns SomeObject
TempData.Get<bool>("SomeBoolKey"); // returns a boolean true
TempData.Get<string>("SomeStringKey"); // returns the string "test"
return View();
}
public ActionResult Index() { TempData.Set("SomeObjectKey", new SomeObject()); TempData.Set("SomeBoolKey", true); TempData.Set("SomeStringKey", "test"); TempData.Get<SomeObject>("SomeObjectKey"); // returns SomeObject TempData.Get<bool>("SomeBoolKey"); // returns a boolean true TempData.Get<string>("SomeStringKey"); // returns the string "test" return View(); }
public ActionResult Index()
{
    TempData.Set("SomeObjectKey", new SomeObject());
    TempData.Set("SomeBoolKey", true);
    TempData.Set("SomeStringKey", "test");
     
    TempData.Get<SomeObject>("SomeObjectKey"); // returns SomeObject
    TempData.Get<bool>("SomeBoolKey"); // returns a boolean true
    TempData.Get<string>("SomeStringKey"); // returns the string "test"
 
    return View();
}

You can also do the same with ViewData:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public static class ViewDataExtensions
{
public static T Get<T>(this ViewDataDictionary viewData, string key)
{
if (viewData[key] is T)
{
var viewDataItem = (T)viewData[key];
return viewDataItem;
}
throw new InvalidCastException(string.Format("View Data does not contain type {0} for key {1}", typeof(T), key));
}
public static void Set<T>(this ViewDataDictionary viewData, string key, T value)
{
viewData[key] = value;
}
}
public static class ViewDataExtensions { public static T Get<T>(this ViewDataDictionary viewData, string key) { if (viewData[key] is T) { var viewDataItem = (T)viewData[key]; return viewDataItem; } throw new InvalidCastException(string.Format("View Data does not contain type {0} for key {1}", typeof(T), key)); } public static void Set<T>(this ViewDataDictionary viewData, string key, T value) { viewData[key] = value; } }
public static class ViewDataExtensions
{
    public static T Get<T>(this ViewDataDictionary viewData, string key)
    {
        if (viewData[key] is T)
        {
            var viewDataItem = (T)viewData[key];
            return viewDataItem;
        }
        throw new InvalidCastException(string.Format("View Data does not contain type {0} for key {1}", typeof(T), key));
    }
 
    public static void Set<T>(this ViewDataDictionary viewData, string key, T value)
    {
        viewData[key] = value;
    }
}

I know what you are thinking, this doesn’t stop you from setting TempData the <string, object> way, and you are correct.  To get and set using strong types, you have to have the discipline to use these extension methods.  But, with these tools, you can give yourself a fighting chance.

Published in.netc#csharpmvc

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *