【问题标题】:How to get current culture for app.UseExceptionHandler method that in Startup.cs's Configure method?如何在 Startup.cs 的 Configure 方法中获取 app.UseExceptionHandler 方法的当前文化?
【发布时间】:2020-05-22 19:57:26
【问题描述】:

我有一个使用 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-core model-view-controller


    【解决方案1】:

    你要做的是一个中间件,我们称之为ExceptionHtmlHandler,你必须从Header中获取"Accept-Language"才能知道他来自哪里。 如果要返回 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&lt;ExceptionHtmlHandler&gt;();

    最后,对于你的控制器,类似的事情就可以了,我认为你不需要使用路由:

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

    【讨论】:

    • 你好,我的朋友。谢谢你的想法。我尝试了您的代码,您使用了标题的“接受语言”。但是在我的代码中,Header 的“Accept-Language”是空的,因此我检查 context.Request.Path 以了解 dedect 文化。我最终决定,基于 UseStatusCodePagesWithReExecute 重写自己的中间件。我将检查 UseStatusCodePagesWithReExecute 或 ExceptionHandlerMiddleware - github.com/aspnet/Diagnostics/blob/… 的源代码。它对我有用。感谢您的想法
    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 2017-02-22
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多