在 TempData 中存储复杂对象

我一直试图通过像下面这样使用 TempData 将数据传递给重定向后的操作:

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

但不幸的是,它在下面的信息中失败了:

System.InvalidOperationException Microsoft.AspNet.Mvc.SessionStateTempDataProvider'无法序列化 类型为 'ModelStateDictionary'的对象转换为会话状态

我在 Github 中的 MVC 项目中发现了一个问题,但是虽然它解释了为什么我会得到这个错误,但是我不知道什么是可行的替代方案。

一种选择是将对象序列化为 json 字符串,然后将其反序列化并重新构造 ModelState。这是最好的办法吗?我是否需要考虑任何潜在的性能问题?

最后,对于序列化复杂对象或使用不涉及使用 TempData的其他模式,是否有其他选择?

35816 次浏览

您可以像下面这样创建扩展方法:

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

你可以这样使用它们:

假设 objectAClassA类型。您可以使用上面提到的扩展方法将其添加到临时数据字典,如下所示:

TempData.Put("key", objectA);

要找回它,你可以这样做:

var value = TempData.Get<ClassA>("key") 检索到的 value将是 ClassA类型的

我不能评论,但我添加了一个 PEEK,这是很好的检查是否有或读取,而不是为下一个 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);
}

例子

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

在.Net 核心3.1及以上版本中使用 系统,短信,杰森

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