首页 > 解决方案 > 如何在 Startup.cs 的 Configure 方法中获取 app.UseExceptionHandler 方法的当前文化?

问题描述

我有一个用 ASP.NET Core 3.1 MVC 编写的多语言网站。

它支持两种语言:阿塞拜疆语和英语。它使用路由基础本地化。

我设置 app.UseExceptionHandler(...)了使用例外页面,如下所示。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
       app.UseExceptionHandler("/en/main/error");
       app.UseHsts();
    }

    app.UseStatusCodePagesWithReExecute("/en/main/error", "?code={0}");
    ...
}

但我有一个问题。问题是我的异常页面总是使用"en"文化。

因为我硬编码了app.UseExceptionHandler的errorEandlingPath。(app.UseExceptionHandler("/en/main/error");app.UseStatusCodePagesWithReExecute("/en/main/error", "?code={0}");)

我的站点的路由配置如下:

...
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(name: "default", pattern: "{culture=az}/{controller=Main}/{action=Index}/{id?}");
    }
...

如何动态设置当前文化app.UseExceptionHandler("/en/main/error");

例如:如果用户使用阿塞拜疆文化,errorEandlingPath 必须是"/az/main/error",否则"/en/main/error"

我试过了

app.UseExceptionHandler("/{culture}/main/error");

app.UseStatusCodePagesWithReExecute("/{culture}/main/error", "?code={0}");

但两者都不起作用。请帮助我,谢谢)

标签: c#asp.net-coremodel-view-controller

解决方案


你需要做的是一个中间件,让我们调用它ExceptionHtmlHandler,你必须"Accept-Language"从 Header 中获取它才能知道他来自哪里。如果要返回 404/403/等,则需要根据异常进行控制。

这是中间件:

public class ExceptionHtmlHandler
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (YourException e)
        {
            context.RequestServices
                   .GetService<ILogger>()
                   .Error(e);

            PersonalizedMethod1(context, e);
        }
        catch (Exception e)
        {
          context.RequestServices
                 .GetService<ILogger>()
                 .Error(e);
            HandleException(context, e);
        }
    }

    private static void PersonalizedMethod1(HttpContext context, Exception e)
    {
        var lang = context.Request.Headers["Accept-Language"];
        var errorCode = HttpStatusCode.BadRequest;
        context.Response.StatusCode =(int)errorCode;
        context.Response.Redirect($"/{lang}/main/error/{errorCode}");
    }

    // other errors
    private static void HandleException(HttpContext context, Exception e)
    {
        context.Response.Redirect("/error");
    }
}

要在你的startup.cs而不是app.UseExceptionHandler("/en/main/error");你可以使用它app.UseMiddleware<ExceptionHtmlHandler>();

最后,对于您的控制器,类似的事情会做,我认为您不需要使用路由:

[HttpGet("{lang}/main/error/{errorCode}")]
public async Task<ViewResult> Error(string lang,int errorCode )
{
    return View("Error", await GetErrorTranslated(lang,errorCode  ));
}

推荐阅读