【发布时间】:2015-07-16 07:07:25
【问题描述】:
目前,我的 ASP.NET MVC 网站使用RouteConfig.RegisterRoutes 来映射路线。我想将其转换为新的 Attribute 路由系统,但我在那里遗漏了一件小事。
该网站是多语言的,因此每个 URL 都需要以两个字母的 ISO 语言代码作为前缀。
在当前的实现中,网站使用自定义的RouteHandler 来处理所有路由的文化部分。注册所有路由后,循环将自定义处理程序和区域性约束添加到每个路由。
查看下面的当前实现:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.RouteExistingFiles = true;
// various calls to routes.MapRoute()
foreach (Route r in routes)
{
if (!(r.RouteHandler is SingleCultureMvcRouteHandler))
{
r.RouteHandler = new MultiCultureMvcRouteHandler();
r.Url = "{culture}/" + r.Url;
// Add the default language
if (r.Defaults == null)
r.Defaults = new RouteValueDictionary();
r.Defaults.Add("culture", Culture.nl.ToString());
// Add language constraints
if (r.Constraints == null)
r.Constraints = new RouteValueDictionary();
r.Constraints.Add("culture", new CultureConstraint(Culture.nl.ToString(), Culture.de.ToString(), Culture.en.ToString(), Culture.fr.ToString()));
}
}
}
}
文化枚举:
public enum Culture
{
nl = 1,
en = 2,
de = 3,
fr = 4
}
自定义路由处理程序:
public class SingleCultureMvcRouteHandler : MvcRouteHandler { }
public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var culture = requestContext.RouteData.Values["culture"].ToString();
var ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");
return base.GetHttpHandler(requestContext);
}
}
文化限制
public class CultureConstraint : IRouteConstraint
{
private string[] _values;
public CultureConstraint(params string[] values)
{
this._values = values;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string value = values[parameterName].ToString();
return _values.Contains(value);
}
}
为了将其转换为新的 AttributeRouting,我只是想在我的基本控制器中添加一个 RoutePrefix 属性,它可以处理文化部分。 但是似乎不支持路由属性的继承...
ASP.NET MVC 5.2 的release notes 声明,通过实现自定义RouteAttribute 和DirectRouteProvider,该版本支持继承的路由属性。但是,这适用于RouteAttribute,而不适用于RoutePrefixAttribute。
我尝试过的:
我尝试通过从RoutePrefixAttribute 继承来创建自己的InheritedRoutePrefixAttribute,但是为了真正支持继承的路由,我仍然需要创建InheritedDirectRouteProvider 并覆盖GetControllerRouteFactories() 方法,它返回 IDirectRouteFactory 的集合。
所以为了做到这一点,我的InheritedRoutePrefixAttribute需要实现IDirectRouteFactory接口,但是在CreateRoute()方法中要做什么呢?
到目前为止我的代码:
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class InheritedRoutePrefixAttribute : RoutePrefixAttribute, IDirectRouteFactory
{
public RouteEntry CreateRoute(DirectRouteFactoryContext context)
{
// ...
}
}
自定义路由提供者
// Custom direct route provider which supports attribute route inheritance.
public class InheritedDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory> GetControllerRouteFactories(ControllerDescriptor controllerDescriptor)
{
return controllerDescriptor.GetCustomAttributes(typeof(InheritedRoutePrefixAttribute), inherit: true).Cast<IDirectRouteFactory>().ToArray();
}
}
【问题讨论】:
-
你有没有设法让它工作?我目前正在尝试...
-
@MartinHansenLennox 不,我没有。我只是将属性设置为每个控制器。它可能在 ASP.NET Core 中得到支持,但说实话我不知道。
-
感谢您回来。我也做不到,所以我继续前进……但如果路过这里的人知道,我仍然会对答案感兴趣……
标签: c# asp.net-mvc routing asp.net-mvc-routing attributerouting