Store complex object in TempData

C#asp.net Coreasp.net Core-MvcTempdata

C# Problem Overview


I've been trying to pass data to an action after a redirect by using TempData like so:

if (!ModelState.IsValid)
{
	TempData["ErrorMessages"] = ModelState;
	return RedirectToAction("Product", "ProductDetails", new { code = model.ProductCode });
}

but unfortunately it's failing with the following message:

> 'System.InvalidOperationException The > Microsoft.AspNet.Mvc.SessionStateTempDataProvider' cannot serialize an > object of type 'ModelStateDictionary' to session state.'

I've found an issue in the MVC project in Github, but while it explains why I'm getting this error, I can't see what would be a viable alternative.

One option would be to serialize the object to a json string and then deserialize it back and reconstruct the ModelState. Is this the best approach? Are there any potential performance issues I need to take into account?

And finally, are there any alternatives for either serializing complex object or using some other pattern that doesn't involve using TempData?

C# Solutions


Solution 1 - C#

You can create the extension methods like this:

public static class TempDataExtensions
{
	public static void Put<T>(this ITempDataDictionary tempData, string key, T value) where T : class
	{
		tempData[key] = JsonConvert.SerializeObject(value);
	}

	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);
	}
}

And, you can use them as follows:

Say objectA is of type ClassA. You can add this to the temp data dictionary using the above mentioned extension method like this:

TempData.Put("key", objectA);

And to retrieve it you can do this:

var value = TempData.Get<ClassA>("key") where value retrieved will be of type ClassA

Solution 2 - C#

I can not comment but I added a PEEK as well which is nice to check if there or read and not remove for the next GET.

public static T Peek<T>(this ITempDataDictionary tempData, string key) where T : class
{
    object o = tempData.Peek(key);
    return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
}

Example

var value = TempData.Peek<ClassA>("key") where value retrieved will be of type ClassA

Solution 3 - C#

Using System.Text.Json in .Net core 3.1 & above

using System.Text.Json;

    public static class TempDataHelper
    {
        public static void Put<T>(this ITempDataDictionary tempData, string key, T value) where T : class
        {
            tempData[key] = JsonSerializer.Serialize(value);
        }

        public static T Get<T>(this ITempDataDictionary tempData, string key) where T : class
        {
            tempData.TryGetValue(key, out object o);
            return o == null ? null : JsonSerializer.Deserialize<T>((string)o);
        }

        public static T Peek<T>(this ITempDataDictionary tempData, string key) where T : class
        {
            object o = tempData.Peek(key);
            return o == null ? null : JsonSerializer.Deserialize<T>((string)o);
        }
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionelolosView Question on Stackoverflow
Solution 1 - C#hemView Answer on Stackoverflow
Solution 2 - C#Chris GoView Answer on Stackoverflow
Solution 3 - C#AjtView Answer on Stackoverflow