2016-07-21 2 views
19

Я wokring в новом приложении mvc для Asp.Net. Я определил маршрут с пользовательским ограничением, который устанавливает текущую культуру приложения из URL-адреса. Я пытаюсь управлять локализации для моего приложения путем создания пользовательских IRequestCultureProvider который выглядит следующим образом:Asp.Net core get RouteData value from url

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, я имел Possiblity вручную обработать мой URL через процесс маршрутизации, делая это

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

я не могу найти способ сделать то же самое в новом framewrok права Теперь. Кроме того, я хочу использовать данные маршрута, чтобы узнать мои langugae, анализируя мою строку url с некоторыми строковыми функциями, чтобы найти язык не является вариантом.

+0

Это [вопрос и ответ] (http://stackoverflow.com/questions/35829426/optionally-override-request-culture-via-url-route-in -an-asp-net-core-1-0-applica/35970676 # 35970676) может помочь –

+0

@nboisvert Не могли бы вы решить эту проблему? – SherleyDev

+0

@SherleyDev см. Мой ответ –

ответ

7

Существует не простой способ сделать это, и команда ASP.Net еще не решила реализовать эту функциональность. 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?}"); 
    }; 

Добавить новое связующее:

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

Возможно, у вас есть t • определять этот класс, а ...

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

Это сработало хорошо для меня, мне нужно было ge – Ben

+0

wow только возможность редактировать комментарии на 5 минут - это боль! это то, что я хотел сказать: мне нужно было получить доступ к параметру в каком-то другом промежуточном программном обеспечении, и это сделало работу для меня практически без изменений! 5 * будет использовать снова – Ben