在启用了LowercaseUrls的Route参数中保留Case

我正在使用routes.LowercaseUrls = true; 在我的MVC 4应用程序中工作得很好。 但是,参数也会变低,所以如果我有一个像这样的路线

 routes.MapRoute( name: "MyController", url: "foo/{hash}/{action}", defaults: new { controller = "MyController", action = "Details" } ); 

生成的链接

 @Html.ActionLink("my link", "Details", new { hash=ViewBag.MyHash }) 

也会将URL的{hash} – 部分小写,例如,如果ViewBag.MyHash = "aX3F5U"则生成的链接将是/foo/ax3f5u而不是/foo/aX3F5U

有没有办法强制MVC只小写控制器和动作部分?

对于旧版本的MVC,前进的方法似乎是实现Route的自定义子类,但是我不知道如何/在哪里实例化它,因为路由构造函数的签名与MapRoute和我是完全不同的希望有一个更简单的方法。

我认为使用Route的自定义子类的解决方案将足够简单,但同时有点丑陋:)

您可以在RouteConfig.cs RegisterRoute方法中添加CustomRoute 。 添加以下代码而不是routes.MapRoute

 var route = new CustomRoute(new Route( url: "{controller}/{action}/{id}", defaults: new RouteValueDictionary() { { "controller", "Home" }, { "action", "Index" }, { "id", UrlParameter.Optional } }, routeHandler: new MvcRouteHandler() )); routes.Add(route); 

特定CustomRoute实现可能如下所示:

 public class CustomRoute : RouteBase { private readonly RouteBase route; public CustomRoute(RouteBase route) { this.route = route; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { values = new RouteValueDictionary(values.Select(v => { return v.Key.Equals("action") || v.Key.Equals("controller") ? new KeyValuePair(v.Key, (v.Value as String).ToLower()) : v; }).ToDictionary(v => v.Key, v => v.Value)); return route.GetVirtualPath(requestContext, values); } public override RouteData GetRouteData(HttpContextBase httpContext) { return route.GetRouteData(httpContext); } } 

然而,这不是最佳实施。 一个完整的示例可以在RouteCollection和自定义RouteRouteCollection上使用扩展组合,以使其尽可能接近原始routes.MapRoute(...)语法:

LowercaseRoute类:

 public class LowercaseRoute : Route { public LowercaseRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { values = new RouteValueDictionary(values.Select(v => { return v.Key.Equals("action") || v.Key.Equals("controller") ? new KeyValuePair(v.Key, (v.Value as String).ToLower()) : v; }).ToDictionary(v => v.Key, v => v.Value)); return base.GetVirtualPath(requestContext, values); } } 

RouteCollectionExtensions类:

 public static class RouteCollectionExtensions { [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url) { return MapLowercaseRoute(routes, name, url, null /* defaults */, (object)null /* constraints */); } [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults) { return MapLowercaseRoute(routes, name, url, defaults, (object)null /* constraints */); } [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, object constraints) { return MapLowercaseRoute(routes, name, url, defaults, constraints, null /* namespaces */); } [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, string[] namespaces) { return MapLowercaseRoute(routes, name, url, null /* defaults */, null /* constraints */, namespaces); } [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) { return MapLowercaseRoute(routes, name, url, defaults, null /* constraints */, namespaces); } [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } Route route = new LowercaseRoute(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { route.DataTokens["Namespaces"] = namespaces; } routes.Add(name, route); return route; } private static RouteValueDictionary CreateRouteValueDictionary(object values) { var dictionary = values as IDictionary; if (dictionary != null) { return new RouteValueDictionary(dictionary); } return new RouteValueDictionary(values); } } 

您现在可以使用MapLowercaseRoute而不是MapRoute

 routes.MapRoute( name: "MyController", url: "foo/{hash}/{action}", defaults: new { controller = "MyController", action = "Details" } ); 

简直成了

 routes.MapLowercaseRoute( name: "MyController", url: "foo/{hash}/{action}", defaults: new { controller = "MyController", action = "Details" } ); 

暴露出期望的行为。

这是一个简单的方法,

 public class MyRoute : Route { public MyRoute(string url, object defaults): base(url, new RouteValueDictionary(defaults), new MvcRouteHandler()) { } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { if (values["action"] != null) values["action"] = values["action"].ToString().ToLowerInvariant(); if (values["controller"] != null) values["controller"] = values["controller"].ToString().ToLowerInvariant(); return base.GetVirtualPath(requestContext, values); } } routes.Add("Default",new MyRoute("{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = MyUrlParameter.Optional })); 

有关详细信息 ,请参阅此博文 。

如果你看一下私有的RouteCollection.NormalizeVirtualPath方法,你会发现它只是使用了virtualPath.ToLowerInvariant() 。 所以没有办法解决这个问题。 即使您创建自己的路线,它也会降低。

但你可以做的是在’#’符号之后添加哈希,即"foo/{action}/#{hash}" 。 我没有尝试,但它应该工作。 只需看看NormalizeVirtualPath实现。

这很简单,如1.2.3,

看看这个例子

  routes.MapRouteLowercase( // changed from routes.MapRoute "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); 

通过Nuget下载和安装它很简单,我使用它。 PM> Install-Package LowercaseRoutesMVC

http://lowercaseroutesmvc.codeplex.com/