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

ASP.NET Core自定义中间件无法重定向问题排查

问题分析与解决方案

核心问题

  1. 重定向后继续执行管道引发异常:调用context.Response.Redirect(redir)后,HTTP响应的状态码和Location头已发送,此时再执行await _next.Invoke(context)会导致后续中间件尝试修改已完成的响应,触发异常导致程序停止。
  2. 文化设置方式不符合框架规范:直接修改CultureInfo.CurrentCulture/CurrentUICulture仅对当前线程的即时操作有效,ASP.NET Core后续的请求处理环节(如控制器、视图)不会自动继承该设置,应使用框架内置的IRequestCultureFeature机制。
  3. UseWhen条件与中间件逻辑冲突:Program.cs中UseWhen强制要求请求包含Culture查询参数,但中间件内部又处理了无该参数的场景(从Session/Cookie/默认配置获取文化),逻辑不匹配。

修复后的中间件代码

public class SetCulture
{
    private readonly RequestDelegate _next;

    public SetCulture(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context, IAssetsConfigAccessor config)
    {
        string cultureName = string.Empty;

        // 优先从查询参数获取文化
        if (context.Request.Query.TryGetValue("culture", out var queryCulture))
        {
            cultureName = queryCulture;
            // 持久化到Session和Cookie
            context.Session.SetString("Culture", cultureName);
            context.Response.Cookies.Append("Culture", cultureName, new CookieOptions
            {
                Expires = DateTimeOffset.UtcNow.AddYears(1),
                Path = "/"
            });
        }
        // 其次从Session获取
        else if (context.Session.TryGetValue("Culture", out var sessionCulture))
        {
            cultureName = Encoding.UTF8.GetString(sessionCulture);
        }
        // 再从Cookie获取
        else if (context.Request.Cookies.TryGetValue("Culture", out var cookieCulture))
        {
            cultureName = cookieCulture;
        }
        // 最后从配置获取默认文化
        else
        {
            var site = await config.GetSiteAsync();
            if (site.Cultures?.Any() == true)
            {
                var defaultSiteCulture = site.Cultures.FirstOrDefault(c => c.IsDefault);
                cultureName = defaultSiteCulture?.Culture.Name ?? Thread.CurrentThread.CurrentCulture.Name;
            }
            else
            {
                var defaultCulture = await config.GetCultureAsync(false);
                cultureName = defaultCulture.Name;
            }
            context.Session.SetString("Culture", cultureName);
        }

        // 使用ASP.NET Core内置机制设置请求文化
        var cultureInfo = new CultureInfo(cultureName);
        var requestCulture = new RequestCulture(cultureInfo, cultureInfo);
        context.Features.Set<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, null));

        // 兼容依赖线程文化的场景
        CultureInfo.CurrentCulture = cultureInfo;
        CultureInfo.CurrentUICulture = cultureInfo;

        // 获取重定向地址
        string returnUrl = context.Request.Query.TryGetValue("returnUrl", out var url) ? url : "/";

        // 执行重定向,终止管道
        context.Response.Redirect(returnUrl);
        // 注意:此处禁止调用await _next.Invoke(context);
    }
}

调整Program.cs配置

  1. 确保Session中间件在SetCulture之前注册(中间件依赖Session功能):
// 先注册Session
app.UseSession();

// 调整UseWhen条件,移除对Culture参数的强制要求
app.UseWhen(cntx => cntx.Request.Path.StartsWithSegments("/Assets/SetCulture"), 
            bld => { bld.UseMiddleware<SetCulture>(); });

额外说明

  • 重定向是终止性操作,处理完成后必须停止管道执行,否则会导致响应状态混乱。
  • 使用IRequestCultureFeature设置文化后,ASP.NET Core的模型绑定、视图本地化等环节会自动适配该文化,比直接修改线程文化更可靠。
  • 将文化保存到Cookie后,后续请求会自动携带该Cookie,可在全局中间件中读取并自动设置文化,无需重复调用/Assets/SetCulture接口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:16:02