ASP.Net Core: Storing objects in TempData


There may come a time where you want to store non string data in your site's TempData. Upon doing this you will likely be met with the following exception.

Exception

    System.InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type 'App.AppClasses.MyTestClass'.
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer.EnsureObjectCanBeSerialized(Object item)
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer.Serialize(IDictionary`2 values)
       at Microsoft.AspNetCore.Mvc.ViewFeatures.SessionStateTempDataProvider.SaveTempData(HttpContext context, IDictionary`2 values)
       at Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary.Save()
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.SaveTempData(IActionResult result, ITempDataDictionaryFactory factory, HttpContext httpContext)
       at Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.SaveTempDataFilter.OnResultExecuted(ResultExecutedContext context)
       at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__22.MoveNext()

The ASP.Net Core team made a decision to not try to automatically serialize complex data with the rationale that only the caller will truly know how it needs to be serialized in all cases (which is fair). As a frequent caller I can catch 90% (I made this number up) of my cases by serializing to JSON with JSON.Net. The following are two extension methods which will allow you to put data into the TempData and then retrieve it (these use Newtonsoft JSON.Net to serialize and deserialize).

C# Extension Methods

/// <summary>
/// Puts an object into the TempData by first serializing it to JSON.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tempData"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static void Put<T>(this ITempDataDictionary tempData, string key, T value) where T : class
{
    tempData[key] = JsonConvert.SerializeObject(value);
}

/// <summary>
/// Gets an object from the TempData by deserializing it from JSON.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tempData"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T Get<T>(this ITempDataDictionary tempData, string key) where T : class
{
    object o;
    tempData.TryGetValue(key, out o);
    return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
}