Asp.Net 核心 Tempdata 和 redirecttoaction 不工作
Asp.Net core Tempdata and redirecttoaction not working
我的 basecontroller class 中有一个方法可以将数据添加到临时数据以显示弹出消息。
protected void AddPopupMessage(SeverityLevels severityLevel, string title, string message)
{
var newPopupMessage = new PopupMessage()
{
SeverityLevel = severityLevel,
Title = title,
Message = message
};
_popupMessages.Add(newPopupMessage);
TempData["PopupMessages"] = _popupMessages;
}
如果操作 returns 一个视图,这工作正常。如果该操作正在调用重定向操作,我会收到以下错误。
InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type
有什么想法吗?
TempData
使用 Session
,后者本身使用 IDistributedCache
。 IDistributedCache
没有接受对象或序列化对象的能力。因此,您需要自己执行此操作,即:
TempData["PopupMessages"] = JsonConvert.SerializeObject(_popupMessages);
然后,当然,在重定向之后,您需要将其反序列化回您需要的对象:
ViewData["PopupMessages"] = JsonConvert.DeserializeObject<List<PopupMessage>>(TempData["PopupMessages"]);
我发生此类错误的另一种情况是从 AspNetCore 2.2 升级到 3.0 - 我将 AzureAD 作为 OpenID Connect 提供程序 - 当它尝试处理 AzureAD cookie 时,它抛出了一个异常TempDataProvider 并抱怨它无法序列化 Int64 类型。这个固定:
services.AddMvc()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());
我试图将一个 Exception 对象序列化到 TempData,但最终不得不创建我自己的 TempDataSerializer 来让它工作(我正在将一些现有代码迁移到 Core)。
// Startup.cs
services.AddSingleton<TempDataSerializer, JsonTempDataSerializer>();
// JsonTempDataSerializer.cs
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
public class JsonTempDataSerializer : TempDataSerializer
{
private readonly JsonSerializer _jsonSerializer = JsonSerializer.CreateDefault(new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All, // This may have security implications
});
public override byte[] Serialize(IDictionary<string, object>? values)
{
var hasValues = values?.Count > 0;
if (!hasValues)
return Array.Empty<byte>();
using var memoryStream = new MemoryStream();
using var writer = new BsonDataWriter(memoryStream);
_jsonSerializer.Serialize(writer, values);
return memoryStream.ToArray();
}
public override IDictionary<string, object> Deserialize(byte[] unprotectedData)
{
using var memoryStream = new MemoryStream(unprotectedData);
using var reader = new BsonDataReader(memoryStream);
var tempDataDictionary = _jsonSerializer.Deserialize<Dictionary<string, object>>(reader)
?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
return tempDataDictionary;
}
};
我的 basecontroller class 中有一个方法可以将数据添加到临时数据以显示弹出消息。
protected void AddPopupMessage(SeverityLevels severityLevel, string title, string message)
{
var newPopupMessage = new PopupMessage()
{
SeverityLevel = severityLevel,
Title = title,
Message = message
};
_popupMessages.Add(newPopupMessage);
TempData["PopupMessages"] = _popupMessages;
}
如果操作 returns 一个视图,这工作正常。如果该操作正在调用重定向操作,我会收到以下错误。
InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type
有什么想法吗?
TempData
使用 Session
,后者本身使用 IDistributedCache
。 IDistributedCache
没有接受对象或序列化对象的能力。因此,您需要自己执行此操作,即:
TempData["PopupMessages"] = JsonConvert.SerializeObject(_popupMessages);
然后,当然,在重定向之后,您需要将其反序列化回您需要的对象:
ViewData["PopupMessages"] = JsonConvert.DeserializeObject<List<PopupMessage>>(TempData["PopupMessages"]);
我发生此类错误的另一种情况是从 AspNetCore 2.2 升级到 3.0 - 我将 AzureAD 作为 OpenID Connect 提供程序 - 当它尝试处理 AzureAD cookie 时,它抛出了一个异常TempDataProvider 并抱怨它无法序列化 Int64 类型。这个固定:
services.AddMvc()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());
我试图将一个 Exception 对象序列化到 TempData,但最终不得不创建我自己的 TempDataSerializer 来让它工作(我正在将一些现有代码迁移到 Core)。
// Startup.cs
services.AddSingleton<TempDataSerializer, JsonTempDataSerializer>();
// JsonTempDataSerializer.cs
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
public class JsonTempDataSerializer : TempDataSerializer
{
private readonly JsonSerializer _jsonSerializer = JsonSerializer.CreateDefault(new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All, // This may have security implications
});
public override byte[] Serialize(IDictionary<string, object>? values)
{
var hasValues = values?.Count > 0;
if (!hasValues)
return Array.Empty<byte>();
using var memoryStream = new MemoryStream();
using var writer = new BsonDataWriter(memoryStream);
_jsonSerializer.Serialize(writer, values);
return memoryStream.ToArray();
}
public override IDictionary<string, object> Deserialize(byte[] unprotectedData)
{
using var memoryStream = new MemoryStream(unprotectedData);
using var reader = new BsonDataReader(memoryStream);
var tempDataDictionary = _jsonSerializer.Deserialize<Dictionary<string, object>>(reader)
?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
return tempDataDictionary;
}
};