我有一个带有请求本地化的 Net8 Web 应用程序。当抛出错误时,它无法导航到错误页面,因为它将 URL 中的错误视为文化并尝试导航到http://localhost:5245/Error/Index
.
如果我指定app.UseExceptionHandler("/en/Error")
它是成功的,但我无法以另一种语言提供该页面。
我在编写自定义错误处理程序方面取得了一些成功,但我想将用户重定向到错误页面,因为包含页面导航,而不是返回纯文本或手动编码 HTML。
程序.cs
using System.Globalization;
using LocalizationWithErrors.Conventions;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Localization.Routing;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("fr"),
};
options.DefaultRequestCulture = new RequestCulture(supportedCultures[0]);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider() { Options = options });
});
services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
});
var app = builder.Build();
/*
It works if I include the language in the path to the
ExceptionHandler page, but I'm not able to add the path for multiple supported languages
*/
// app.UseExceptionHandler("/en/Error");
app.UseExceptionHandler("/Error");
var localizationOptions = app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value;
app.UseRouting();
app.UseStaticFiles();
app.UseRequestLocalization(localizationOptions);
app.MapRazorPages();
app.Run();
RouteModelConvention:这将为应用程序中的所有页面创建每个支持区域性的路由模型约定。
en/Index
,,,,,,,fr/index
en/Privacy
fr/Privacy
en/Error
fr/Error
我尝试在约定中排除/包括错误页面,以查看它如何影响路由,但它没有看到任何效果。
GlobalTemplatePageRouteModelConvention.cs
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace LocalizationWithErrors.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count();
if (!model.RelativePath.Contains("Error"))
{
for (int i = 0; i < selectorCount; i++)
{
SelectorModel selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = -1,
Template = AttributeRouteModel.CombineTemplates("{culture}",
selector.AttributeRouteModel!.Template
),
}
});
}
}
}
}
页面/Index.cshtml
@page
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@model IndexModel
@{
ViewData["Title"] = "Home page";
var requestCultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>CultureInfo: @requestCultureFeature.RequestCulture.Culture</p>
<p>CurrentUICulture: @requestCultureFeature.RequestCulture.UICulture</p>
</div>
<form method="POST">
<button type="submit">Cause an error</button>
</form>
页面/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace LocalizationWithErrors.Pages;
public class IndexModel : PageModel
{
/* Throw an exception to trigger the Error handler */
public async Task<IActionResult> OnPost() => throw new FileNotFoundException("Whoops");
}
页面/Error.cshtml
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
页面/Error.cshtml.cs
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace LocalizationWithErrors.Pages;
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public void OnGet() => RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
如何将文化包含在错误页面的路由中?
编辑 2024-04-09 22:40 (-5:00 GMT) 根据 @ Guru Stron的请求,我编辑了该帖子以包含重新创建问题所需的所有代码。
尝试添加自定义中间件,例如:
MyCustomExceptionHandlerMiddleware
,并注册它。MyCustomExceptionHandlerMiddleware.cs
注册一下
测试结果