首页 文章

Asp.Net核心从url获取RouteData值

提问于
浏览
21

我想通过创建自定义 IRequestCultureProvider 来管理我的应用的本地化,如下所示:

public class MyCustomRequestCultureProvider : IRequestCultureProvider
    {
        public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
        {
            var language= httpContext.GetRouteValue("language");

            var result = new ProviderCultureResult(language, language);
            return Task.FromResult(result);
        }
    }

我的 MyCustomRequestCultureProvider 在每个请求都被点击,这没关系 . 我的问题是在MVC管道中,我的提供程序的 DetermineProviderCultureResult 方法在路由进程之前被命中,因此 httpContext.GetRouteValue("language") 总是返回null .

在以前版本的MVC中,我有可能通过这样做来通过路由过程手动处理我的url

var wrapper = new HttpContextWrapper(HttpContext.Current);
var routeData = RouteTable.Routes.GetRouteData(wrapper);
var language = routeData.GetValue("language")

我现在找不到在新的framewrok中做同样事情的方法 . 此外,我想使用路由数据找出我的langugae,用一些字符串函数分析我的url字符串,以找到语言不是一个选项 .

2 回答

  • 9

    尚未决定实施此功能 . IRoutingFeature 仅在MVC完成请求后可用 .

    我能够整理出一个适合你的解决方案 . 这将设置您传入 UseMvc() 的路线以及所有属性路由以填充IRoutingFeature . 完成后,您可以通过 httpContext.GetRouteValue("language"); 访问该类 .

    Startup.cs

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // setup routes
        app.UseGetRoutesMiddleware(GetRoutes);
    
        // add localization
        var requestLocalizationOptions = new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("en-US")
        };
        requestLocalizationOptions.RequestCultureProviders.Clear();
        requestLocalizationOptions.RequestCultureProviders.Add(
            new MyCustomRequestCultureProvider()
        );
        app.UseRequestLocalization(requestLocalizationOptions);
    
        // add mvc
        app.UseMvc(GetRoutes);
    }
    

    将路由移动到委托(用于可重用),相同的文件/类:

    private readonly Action<IRouteBuilder> GetRoutes =
        routes =>
        {
            routes.MapRoute(
                name: "custom",
                template: "{language=fr-FR}/{controller=Home}/{action=Index}/{id?}");
    
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        };
    

    Add new middleware:

    public static class GetRoutesMiddlewareExtensions
    {
        public static IApplicationBuilder UseGetRoutesMiddleware(this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }
    
            var routes = new RouteBuilder(app)
            {
                DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
            };
            configureRoutes(routes);
            routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
            var router = routes.Build();
    
            return app.UseMiddleware<GetRoutesMiddleware>(router);
        }
    }
    
    public class GetRoutesMiddleware
    {
        private readonly RequestDelegate next;
        private readonly IRouter _router;
    
        public GetRoutesMiddleware(RequestDelegate next, IRouter router)
        {
            this.next = next;
            _router = router;
        }
    
        public async Task Invoke(HttpContext httpContext)
        {
            var context = new RouteContext(httpContext);
            context.RouteData.Routers.Add(_router);
    
            await _router.RouteAsync(context);
    
            if (context.Handler != null)
            {
                httpContext.Features[typeof (IRoutingFeature)] = new RoutingFeature()
                {
                    RouteData = context.RouteData,
                };
            }
    
            // proceed to next...
            await next(httpContext);
        }
    }
    

    您可能还必须定义此类...

    public class RoutingFeature : IRoutingFeature
    {
        public RouteData RouteData { get; set; }
    }
    
  • 1

    根据Ashley Lee的回答,这是一种防止重复路由配置的优化方法 .

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
       // setup routes
       var mvcRouter = BuildMvcRouter(app, routes =>
       {
           routes.MapRoute(
               name: "custom",
               template: "{language=fr-FR}/{controller=Home}/{action=Index}/{id?}");
           routes.MapRoute(
               name: "default",
               template: "{controller=Home}/{action=Index}/{id?}");
        };
    
        // add route data initialization middleware
        app.Use(next => SetRouteData(next, mvcRouter));
    
        // add localization middleware
        var requestLocalizationOptions = new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("en-US")
        };
        requestLocalizationOptions.RequestCultureProviders.Clear();
        requestLocalizationOptions.RequestCultureProviders.Add(
            new MyCustomRequestCultureProvider()
        );
        app.UseRequestLocalization(requestLocalizationOptions);
    
        // add mvc routing middleware
        app.UseRouter(mvcRouter);
    }
    

    这取决于必须添加到StartUp类的以下两个方法:

    private static IRouter BuildMvcRouter(IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
    {
        if (app == null) throw new ArgumentNullException(nameof(app));
        if (configureRoutes == null) throw new ArgumentNullException(nameof(configureRoutes));
    
        app.ApplicationServices.GetRequiredService<MiddlewareFilterBuilder>().ApplicationBuilder = app.New();
        RouteBuilder routeBuilder = new RouteBuilder(app)
        {
            DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>()
        };
        configureRoutes((IRouteBuilder)routeBuilder);
        routeBuilder.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
    
        return routeBuilder.Build();
    }
    
    private static RequestDelegate SetRouteData(RequestDelegate next, IRouter router)
    {
        return async context =>
        {
            var routeContext = new RouteContext(context);
            await router.RouteAsync(routeContext);
    
            if (routeContext.Handler != null)
            {
                context.Features[typeof(IRoutingFeature)] = new RoutingFeature()
                {
                    RouteData = routeContext.RouteData
                };
            }
    
            await next(context);
        };
    }
    

相关问题