You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC用TempData给中间件传值添加请求头为何失效

问题原因

你当前的实现方式本身不符合TempData的设计定位,失效是正常现象:

  • TempData的生命周期默认是仅单次请求读取有效,只要你读取了对应键的值,该数据就会被自动标记为待删除,哪怕你在控制器调用了TempData.Keep(),在中间件首次读取tempData["username"]后,下一次请求也无法再获取到该值。
  • TempData是为控制器动作间的单次跳转传值设计的,并不适用跨多请求在中间件共享用户数据的场景。

解决方案

你提到的用Session实现是可行的,这也是这种场景下的标准实现思路,具体改造步骤如下:

1. 配置Session服务与中间件顺序

首先在Program.cs中注册Session服务,且必须保证Session中间件在你的自定义中间件之前注册,否则中间件无法读取Session数据:

// 注册Session服务
builder.Services.AddSession(options =>
{
    // 按需设置Session过期时间
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 中间件管道顺序严格遵循:Session -> 自定义中间件 -> MVC相关中间件
app.UseSession();
app.UseMiddleware<CorrelationIdMiddleware>();
app.UseRouting();
// 其他鉴权、授权中间件
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

2. 修改控制器代码,把username存入Session

删除原有的TempData相关逻辑,改为存入Session:

[HttpPost]
public IActionResult AddressValidate(IFormCollection form)
{
    string username = form["UserName"];
    // 将username存入Session
    HttpContext.Session.SetString("username", username);

    string status = form["Status"];
    _logger.LogInformation("Current user logged in: {@Username}", username);
    // 原有业务逻辑
    return RedirectToAction("SecondIndex", "Second");         
}

3. 修改中间件代码,从Session读取username

同时修正你原代码中CorrelationId取值的错误逻辑:

public async Task Invoke(HttpContext httpContext)
{
    string correlationId = null;

    if (httpContext.Request.Headers.TryGetValue(CorrelationIdHeaderKey, out StringValues correlationIds))
    {
        // 修正原有错误的取值逻辑,直接取请求头的值即可
        correlationId = correlationIds.FirstOrDefault();
        _logger.LogInformation("CorrelationId from Request Header: {@correlationId} ", correlationId);
    }
    else
    {
        // 从Session读取username
        var userName = httpContext.Session.GetString("username");
        if (!string.IsNullOrEmpty(userName) && !httpContext.Request.Headers.ContainsKey("X-username"))
        {
            httpContext.Request.Headers.Add("X-username", userName);
        }

        correlationId = Guid.NewGuid().ToString();
        httpContext.Request.Headers.Add(CorrelationIdHeaderKey, correlationId);
        _logger.LogInformation("Generated CorrelationId: {@correlationId}", correlationId);
    }
    httpContext.Response.OnStarting(() =>
    {
        if (!httpContext.Response.Headers.TryGetValue(CorrelationIdHeaderKey, out correlationIds))
        {
            httpContext.Response.Headers.Add(CorrelationIdHeaderKey, correlationId);
        }
        return Task.CompletedTask;
    });
    await _next.Invoke(httpContext);
}

其他可选方案

如果你的系统已经接入了ASP.NET Core身份认证,不需要自己存储username,直接在中间件读取httpContext.User.Identity?.Name即可,比Session方案更安全便捷。

内容的提问来源于stack exchange,提问作者MarkCo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 10:54:02