Asp.Net core 从 url 获取 RouteData 值 [英] Asp.Net core get RouteData value from url

查看:28
本文介绍了Asp.Net core 从 url 获取 RouteData 值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个新的 Asp.Net 核心 mvc 应用程序.我定义了一个带有自定义约束的路由,它从 url 设置当前的应用程序文化.我正在尝试通过创建一个如下所示的自定义 IRequestCultureProvider 来管理我的应用程序的本地化:

I'm wokring on a new Asp.Net core mvc app. I defined a route with a custom constraint, which sets current app culture from the url. I'm trying to manage localization for my app by creating a custom IRequestCultureProvider which looks like this :

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.

My MyCustomRequestCultureProvider is hit on every request, which is ok. My problem is that in the MVC pipeline, DetermineProviderCultureResult method from my provider is hit before the routing process, so httpContext.GetRouteValue("language") always return null.

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

In previous version of MVC, I had the possiblity to manually process my url through the routing process by doing this

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

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

I can't find a way to do the same thing in the new framewrok right now. Also, I want to use the route data to find out my langugae, analysing my url string with some string functions to find the language is not an option.

推荐答案

没有简单的方法可以做到这一点,ASP.Net 团队还没有决定实现这个功能.IRoutingFeature 仅在 MVC 完成请求后可用.

There isn't an easy way to do this, and the ASP.Net team hasn't decided to implement this functionality yet. IRoutingFeature is only available after MVC has completed the request.

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

I was able to put together a solution that should work for you though. This will setup the routes you're passing into UseMvc() as well as all attribute routing in order to populate IRoutingFeature. After that is complete, you can access that class via 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);
}

将路由移至委托(为了可重用性),相同的文件/类:

Moved the routes to a delegate (for re-usability), same file/class:

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?}");
    };

添加新的中间件:

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);
    }
}

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

You may have to define this class as well...

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

这篇关于Asp.Net core 从 url 获取 RouteData 值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆