.NET 7本地化:如何处理NullProviderCultureResult及路由异常问题
.NET 7 Razor页面本地化路由问题解答
现象是否异常?
访问/about时渲染首页的现象不算异常,这是路由匹配逻辑导致的:
- 首页路由
@page "{culture?}"的匹配规则是“可选的culture参数”,路由系统会把/about中的about当作culture参数的值,而首页未校验该参数是否为合法的文化值(pt/en),因此直接渲染首页。 - About页路由
@page "/{culture?}/about"要求URL必须包含culture参数+about后缀,所以/about无法匹配到About页。
是否应该重定向?
从用户体验和路由规范性来看,建议重定向到默认文化对应的/pt/about,既符合本地化配置的默认值,也能让用户访问到正确的页面。
如何自定义NullProviderCultureResult的处理逻辑?
可以通过以下两种方式实现:
1. 自定义请求本地化提供器
继承RouteDataRequestCultureProvider,重写DetermineProviderCultureResult方法,在返回NullProviderCultureResult时返回默认文化:
public class CustomRouteDataRequestCultureProvider : RouteDataRequestCultureProvider { public override Task<ProviderCultureResult?> DetermineProviderCultureResult(HttpContext httpContext) { var baseResult = base.DetermineProviderCultureResult(httpContext).Result; if (baseResult == NullProviderCultureResult) { // 返回预设的默认文化 return Task.FromResult<ProviderCultureResult?>(new ProviderCultureResult("pt", "pt")); } return Task.FromResult(baseResult); } }
在Program.cs中替换原提供器:
builder.Services.Configure<RequestLocalizationOptions>(x => { x.AddSupportedCultures("pt", "en"); x.AddSupportedUICultures("pt", "en"); x.SetDefaultCulture("pt"); x.RequestCultureProviders.Clear(); // 注册自定义提供器 x.AddInitialRequestCultureProvider(new CustomRouteDataRequestCultureProvider { RouteDataStringKey = "culture" }); });
2. 添加自定义中间件处理无文化参数的URL
在UseRequestLocalization之后添加中间件,对无文化参数的About页请求进行重定向:
app.UseRequestLocalization(); app.Use(async (context, next) => { if (context.Request.Path.Equals("/about", StringComparison.OrdinalIgnoreCase)) { // 重定向到默认文化的About页 context.Response.Redirect("/pt/about"); return; } await next(); });
额外优化:校验路由中的culture参数
为避免将非合法值(如about)当作culture传入首页,可在首页PageModel中添加校验逻辑:
public class IndexModel : PageModel { private readonly IOptions<RequestLocalizationOptions> _localizationOpts; public IndexModel(IOptions<RequestLocalizationOptions> localizationOpts) { _localizationOpts = localizationOpts; } public IActionResult OnGet(string? culture) { // 若culture不为空且不在支持列表中,重定向到默认首页 if (!string.IsNullOrEmpty(culture) && !_localizationOpts.Value.SupportedCultures.Any(c => c.Name == culture)) { return Redirect("/"); } return Page(); } }
内容的提问来源于stack exchange,提问作者Miguel Moura
相关产品推荐
相关产品推荐

