Asp.Net 核心临时数据和重定向操作不起作用

Posted

技术标签:

【中文标题】Asp.Net 核心临时数据和重定向操作不起作用【英文标题】:Asp.Net core Tempdata and redirecttoaction not working 【发布时间】:2019-10-24 23:29:59 【问题描述】:

我的 basecontroller 类中有一个方法可以将数据添加到 tempdata 以显示弹出消息。

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;

如果动作返回一个视图,这很好。如果该操作正在调用重定向操作,我会收到以下错误。

InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.TempDataSerializer' cannot serialize an object of type

有什么想法吗?

【问题讨论】:

【参考方案1】:

TempData 使用Session,它本身使用IDistributedCacheIDistributedCache 没有接受对象或序列化对象的能力。因此,您需要自己执行此操作,即:

TempData["PopupMessages"] = JsonConvert.SerializeObject(_popupMessages);

然后,当然,在重定向之后,您需要将其反序列化回您需要的对象:

ViewData["PopupMessages"] = JsonConvert.DeserializeObject<List<PopupMessage>>(TempData["PopupMessages"]);

【讨论】:

这完全从 asp.net 更改为 asp.net core ? 是和不是。不同之处在于 MVC 将默认使用内存中的会话存储,这恰好不需要序列化,然后当您尝试切换到不同的会话存储时会出现异常。虽然 Core 也默认使用内存支持,但 IDistributedCache 接口确保所有会话存储行为相同,即需要对复杂对象进行序列化。 简而言之,您只需在使用内存会话时不必序列化,但内存会话永远不应该在生产中使用。因此,Core 实际上让你为现实世界做好了准备,而 MVC 却没有。 在生产中使用 InMemory 会话有什么问题? 内存是 RAM,它是易失的。如果应用程序停止或它正在运行的服务器重新启动,那么存储在那里的所有内容都消失了。此外,内存受进程限制。如果您在 IIS 中使用容器或 Web 场运行应用程序的多个实例,则每个实例都有自己的内存分配,因此也有自己的会话存储。【参考方案2】:

我遇到此类错误的另一种情况是从 AspNetCore 2.2 升级到 3.0 - 并且,我将 AzureAD 作为 OpenID Connect 提供程序 - 当它尝试处理 AzureAD cookie 时,它​​引发了异常 TempDataProvider 和抱怨它无法序列化一种 Int64。这已修复:

    services.AddMvc()
    .AddNewtonsoftJson(options =>
           options.SerializerSettings.ContractResolver =
              new CamelCasePropertyNamesContractResolver());

https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#newtonsoftjson-jsonnet-support

【讨论】:

【参考方案3】:

我试图将 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;
    
;

【讨论】:

以上是关于Asp.Net 核心临时数据和重定向操作不起作用的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net 核心 MVC 中的本地化不起作用 - 无法找到资源文件

在 Codeigniter 中检查登录和重定向不起作用?

操作过滤器在 asp.net 核心 Web API 中不起作用

我的 Asp.net 核心应用程序事件处理程序不起作用

为啥即使我调用 UseHttpsRedirection ASP.NET Core 重定向也不起作用?

Angular 4 对 asp.net 核心 API 的请求(在标头中使用授权)不起作用