在 TempData 中存储复杂对象
Store complex object in TempData
我一直在尝试通过像这样使用 TempData 在重定向后将数据传递给操作:
if (!ModelState.IsValid)
{
TempData["ErrorMessages"] = ModelState;
return RedirectToAction("Product", "ProductDetails", new { code = model.ProductCode });
}
但不幸的是它失败并显示以下消息:
'System.InvalidOperationException
The
Microsoft.AspNet.Mvc.SessionStateTempDataProvider'
cannot serialize an
object of type 'ModelStateDictionary'
to session state.'
我在 the MVC project in Github 中发现了一个问题,虽然它解释了我收到此错误的原因,但我看不出什么是可行的替代方案。
一种选择是将对象序列化为 json 字符串,然后将其反序列化并重建 ModelState
。这是最好的方法吗?我需要考虑任何潜在的性能问题吗?
最后,对于序列化复杂对象或使用不涉及使用 TempData
的其他模式,是否有任何替代方案?
您可以像这样创建扩展方法:
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);
}
}
而且,您可以按如下方式使用它们:
假设 objectA
是类型 ClassA
。您可以使用上述扩展方法将其添加到临时数据字典中,如下所示:
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 core 3.1 及更高版本中使用 System.Text.Json
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);
}
}
我一直在尝试通过像这样使用 TempData 在重定向后将数据传递给操作:
if (!ModelState.IsValid)
{
TempData["ErrorMessages"] = ModelState;
return RedirectToAction("Product", "ProductDetails", new { code = model.ProductCode });
}
但不幸的是它失败并显示以下消息:
'
System.InvalidOperationException
TheMicrosoft.AspNet.Mvc.SessionStateTempDataProvider'
cannot serialize an object of type'ModelStateDictionary'
to session state.'
我在 the MVC project in Github 中发现了一个问题,虽然它解释了我收到此错误的原因,但我看不出什么是可行的替代方案。
一种选择是将对象序列化为 json 字符串,然后将其反序列化并重建 ModelState
。这是最好的方法吗?我需要考虑任何潜在的性能问题吗?
最后,对于序列化复杂对象或使用不涉及使用 TempData
的其他模式,是否有任何替代方案?
您可以像这样创建扩展方法:
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);
}
}
而且,您可以按如下方式使用它们:
假设 objectA
是类型 ClassA
。您可以使用上述扩展方法将其添加到临时数据字典中,如下所示:
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 core 3.1 及更高版本中使用 System.Text.Json
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);
}
}