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

如何创建.NET Core中间件验证路由参数?解决路由约束注入异常

解决.NET Core 7 Razor Pages路由约束注入RequestLocalizationOptions的异常问题

问题原因

路由约束是在路由构建阶段初始化的,这个阶段DI容器的初始化尚未完成,直接在路由约束的构造函数中注入RequestLocalizationOptions会触发RouteCreationException——因为路由系统无法在路由定义阶段解析依赖服务。硬编码有效文化列表能正常工作,是因为它不需要依赖DI容器。

解决方案:两种可行方案

方案1:调整路由约束的依赖获取方式

不要直接在构造函数注入RequestLocalizationOptions,而是通过IServiceProvider在请求时动态获取服务,避开路由构建阶段的DI限制:

  1. 修改自定义路由约束:
public class CultureRouteConstraint : IRouteConstraint
{
    private readonly IServiceProvider _serviceProvider;

    public CultureRouteConstraint(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.TryGetValue(routeKey, out var cultureValue) || cultureValue is not string culture)
            return false;

        // 在请求时动态获取本地化配置
        var localizationOptions = _serviceProvider.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value;
        var validCultures = localizationOptions.SupportedCultures.Select(c => c.Name).ToList();

        return validCultures.Contains(culture, StringComparer.OrdinalIgnoreCase);
    }
}
  1. 在Program.cs中注册约束和本地化配置:
var builder = WebApplication.CreateBuilder(args);

// 配置本地化选项
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[] { "en", "pt" };
    options.DefaultRequestCulture = new RequestCulture("en");
    options.SupportedCultures = supportedCultures.Select(c => new CultureInfo(c)).ToList();
    options.SupportedUICultures = options.SupportedCultures;
});

// 注册自定义路由约束
builder.Services.AddRouting(options =>
{
    options.ConstraintMap.Add("validculture", typeof(CultureRouteConstraint));
});

builder.Services.AddRazorPages();

var app = builder.Build();

// 启用本地化中间件
app.UseRequestLocalization();

app.UseRouting();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

方案2:改用中间件实现文化验证

如果路由约束的DI问题难以调试,中间件是更灵活的替代方案——中间件运行在请求管道中,DI容器已完全初始化,可直接注入依赖:

  1. 修改Razor页面的路由,移除validculture约束:
@page "/{culture}/about"
  1. 创建文化验证中间件:
public class CultureValidationMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context, IOptions<RequestLocalizationOptions> localizationOptions)
    {
        if (context.Request.RouteValues.TryGetValue("culture", out var cultureValue) && cultureValue is string culture)
        {
            var validCultures = localizationOptions.Value.SupportedCultures.Select(c => c.Name).ToList();
            if (!validCultures.Contains(culture, StringComparer.OrdinalIgnoreCase))
            {
                context.Response.StatusCode = StatusCodes.Status404NotFound;
                // 可自定义返回内容,比如返回项目中的404页面
                await context.Response.WriteAsync("Invalid culture specified");
                return;
            }
        }

        await _next(context);
    }
}
  1. 在Program.cs中注册中间件(注意放在路由中间件之后,端点映射之前):
var app = builder.Build();

// 其他中间件配置...
app.UseRequestLocalization();

app.UseRouting();

// 注册文化验证中间件
app.UseMiddleware<CultureValidationMiddleware>();

app.UseAuthorization();
app.MapRazorPages();

app.Run();

方案对比

  • 路由约束方案:更贴合路由系统的设计,验证逻辑与路由定义绑定,适合简单的参数校验场景。
  • 中间件方案:灵活性更高,可处理更复杂的验证逻辑(比如结合数据库查询验证文化),且DI使用更直观,避免路由构建阶段的依赖问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:40:53