【问题标题】:TempData Cookie Issue. The size of the request headers is too long临时数据 Cookie 问题。请求标头的大小太长
【发布时间】:2020-01-29 15:38:17
【问题描述】:

在Controller中,我通过TempData将错误集合保存到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 中)? 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,我是不是忘记了某些设置?

【问题讨论】:

  • 如您所说,通常如果我们需要在T​​empData中存储大量数据,我们可以使用session provider来代替。此外,启用基于会话的 TempData 提供程序后,请尝试使用浏览器 F12 开发者工具清除现有 cookie,然后浏览您的站点以检查其是否正常工作。
  • 你好韩,我怎么能确定,那个会话提供者有效? cookie 仍在创建中,因此我发布了这个问题。
  • 是的,您可以使用基于会话的临时数据。

标签: session asp.net-core cookies tempdata


【解决方案1】:

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

基于来自docs 的以下示例,您可以通过调用AddSessionStateTempDataProvider 扩展方法来启用基于会话的TempData 提供程序。中间件的order很重要。

注意DefaultTempDataSerializer 指出的限制 这个答案的底部。

示例

她是 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?}");
        });
    }
}

HomeController:

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

【讨论】:

  • Reza,谢谢你,我有你。在本地主机上它可以工作,但是在发布到 IIS 后它会抛出错误 400,现在怎么办? ://
  • 您使用的是哪个版本的 ASP.NET CORE?
  • 版本 2.1 和兼容性版本也是 CompatibilityVersion.Version_2_1。我验证了使用localhost IIS时没有生成cookie,但是切换到开发IIS后,仍然使用CookieTempProvider。
  • 使用有效的解决方案和有效的部署更新了答案。还要注意 DefaultTempDataSerializer 支持的类型限制。
  • 有效!我把骨灰放在头上,因为我在startup.cs 中也有services.AddSingleton&lt;ITempDataProvider, CookieTempDataProvider&gt;();,它否定了会话设置。我不明白我之前没有注意到它。
猜你喜欢
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 2013-07-05
  • 2018-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多