TempData Cookie 问题。请求的大小 headers 太长

TempData Cookie Issue. The size of the request headers is too long

Controller 中,我通过 TempData

将 collection 个错误保存到 cookies
var messages = new List<Message>();
...
TempData.Put("Errors", messages);

TempData.Put是扩展方法

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
        {
            tempData.TryGetValue(key, out object o);
            return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
        }
    }

加载HTML时,我看到

并创建了几个 cookie(Chrome 开发人员工具 > 应用程序 > 存储 > Cookie)

我认为的问题是 Cookie 的总大小在某处达到了某个 Cookie 大小限制。

所以我有两个问题: 是否可以更改 cookie 大小限制(例如 web.config)? 是否可以使用 session 而不是 TempData 的 cookie?

我尝试了第二种方法,如果我更改 startup.cs 文件

\ ConfigureServices method

services.AddMvc()
   .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
   .AddSessionStateTempDataProvider();

services.AddSession();

\ Configure method

app.UseSession();

app.UseMvc(routes =>
{
     routes.MapRoute(
     name: "default",
     template: "{controller=Home}/{action=Index}/{id?}");
});

TempData 仍在使用 Cookie,我是不是忘记了什么设置?

您可以使用 HTTP cookie 或会话状态作为 TempData 的存储机制。基于 cookie 的 TempData 提供程序是默认设置。 您可以阅读有关 Choose a TempData provider.

的更多信息

基于以下示例docs you can enable the session-based TempData provider, by calling AddSessionStateTempDataProvider extension method. The order 中间件很重要。

Be aware of DefaultTempDataSerializer limitations pointed out at bottom of this answer.

例子

她的 a working deployment 使用我为 Srartup 设置的以下设置:

public class Startup
{
    public Startup(IConfiguration configuration) { Configuration = configuration; }
    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .AddSessionStateTempDataProvider();
        services.AddSession();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseSession();
        app.UseMvc(routes => {
            routes.MapRoute(name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

家庭控制器:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        TempData["LargeData"] = new string('a', 1 * 1024 * 1024);
        return View();
    }
}

索引视图:

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome - @(((string)TempData["LargeData"]).Length)</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">
       building Web apps with ASP.NET Core</a>.</p>
</div>

DefaultTempDataSerializer 支持的类型

注意 DefaultTempDataSerializer 支持的类型限制:

public override bool CanSerializeType(Type type)
{
    if (type == null)
    {
        throw new ArgumentNullException(nameof(type));
    }

    type = Nullable.GetUnderlyingType(type) ?? type;

    return
        type.IsEnum ||
        type == typeof(int) ||
        type == typeof(string) ||
        type == typeof(bool) ||
        type == typeof(DateTime) ||
        type == typeof(Guid) ||
        typeof(ICollection<int>).IsAssignableFrom(type) ||
        typeof(ICollection<string>).IsAssignableFrom(type) ||
        typeof(IDictionary<string, string>).IsAssignableFrom(type);
}