在asp.net core 2.2中是否可以针对每个请求截取路由数据并(可能)更改值,例如目标controller
/ action
的值?
我需要使用具有两个字母区域性规范和本地化控制器/动作名称的本地化url方案,例如:
/en/contact-us
/it/contatti
/de/kontakte
我不想使用属性路由来装饰控制器和动作;相反,我想捕获路线数据并以culture
和controller/action
为基础,也许与词典关联一起获得目标控制器和动作。
我已经在asp.net(不是核心)mvc中完成了此类操作。
直到现在,我都可以使用以下代码捕获路由:
app.Use(async (context, next) =>
{
var routeData = context.GetRouteData();
routeData.Values["controller"] = ....;
routeData.Values["action"] = .....;
await next();
});
,但仅对精确映射到现有控制器/动作的url填充路由数据,否则为null;看来这是由于asp.net核心的AttributeRouting.CreateAttributeMegaRoute
方法所致,它仅映射现有的控制器/动作。
答案 0 :(得分:1)
以下是对我有用的解决方案:
// if the route matches this pattern, let's say: app.UseMvc(routeBuilder => { routeBuilder.MapRoute("route1",template: "/{controller=Home}/{action=Index}"); }); // else if the route matches `{culture=en-US}/{controller=Home}/{action=Index}` app.UseRouter(routeBuilder =>{ var template = "{culture=en-US}/{controller=Home}/{action=Index}"; routeBuilder.MapMiddlewareRoute(template, appBuilder =>{ appBuilder.Use(async(context, next)=>{ var routeData = context.GetRouteData(); var controller = routeData.Values["controller"] as string; var action= routeData.Values["action"] as string; var culture= routeData.Values["culture"] as string; // get the real backing path according to current route data context.Request.Path = getNormalizedPath(routeData); await next(); }); appBuilder.UseRequestLocalization(); appBuilder.UseMvc(rb=>{ rb.MapRoute(name:"cultureRoute",template:template); }); });// if you have other MVC routes, add them below:// routeBuilder.MapRoute(name:"mvcRoutes",template: "{area:exists}/{controller=Home}/{action=Index}");}); // else if doesn't match the above pattern, let's say: app.UseMvc(routeBuilder => { routeBuilder.MapRoute("route3",template: "/test/mvc/{controller=Home}/{action=Index}"); });
private string getNormalizedPath(RouteData routeData)
{
var culture= routeData.Values["culture"] as string;
var controller = routeData.Values["controller"] as string;
var action= routeData.Values["action"] as string;
controller = ... real controller according to current culture & controller string
action = ... real action according to current culture & controller string
return $"/{culture}/{controller}/{action}";
}
您需要自定义getNormalizedPath(routeData)
才能获取将被路由到后备控制器/操作的真实路径。
要同时根据当前路径自动设置“请求本地化功能”,您需要插入RouteDataRequestCultureProvider
:
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]{
new CultureInfo("en"),
new CultureInfo("fr"),
new CultureInfo("de"),
new CultureInfo("it"),
};
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
});
@ʞᴉɯ在评论中发现,第一个UseMvc()
在2.2版本中效果不佳。我们需要将MVC兼容性更改为CompatibilityVersion.Version_2_1
:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);