如何在 ASP.NET MVC 中使用小写,加下划线的路由?这样我就可以让 /dinners/details/2调用 DinnersController.Details(2),如果可能的话,让 /dinners/more_details/2调用 DinnersController.MoreDetails(2)?
/dinners/details/2
DinnersController.Details(2)
/dinners/more_details/2
DinnersController.MoreDetails(2)
所有这些仍然使用像 {controller}/{action}/{id}这样的模式。
{controller}/{action}/{id}
当我想做同样的事情并且工作良好时,这两个教程有所帮助:
Http://www.coderjournal.com/2008/03/force-mvc-route-url-lowercase/ Http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/
编辑: 对于带有区域的项目,需要修改 GetVirtualPath ()方法:
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { var lowerCaseValues = new RouteValueDictionary(); foreach (var v in values) { switch (v.Key.ToUpperInvariant()) { case "ACTION": case "AREA": case "CONTROLLER": lowerCaseValues.Add(v.Key, ((string)v.Value).ToLowerInvariant()); break; default: lowerCaseValues.Add(v.Key.ToLowerInvariant(), v.Value); break; } } return base.GetVirtualPath(requestContext, lowerCaseValues); }
这实际上有两个答案:
不过下划线你得靠自己了。
您可以使用 ActionName 属性吗?
[ActionName("more_details")] public ActionResult MoreDetails(int? page) { }
我认为大小写并不重要。 URL 中的 mOrE _ Details、 mOrE _ DETAILS、 mOrE _ DeTaILs 都会将您带到同一个 Controller Action。
我在 Nick Berardi 的编码日志中找到了这个,但是它没有关于如何实现 LowercaseRoute类的信息。因此在这里重新发布附加信息。
LowercaseRoute
首先将 Route类扩展到 LowercaseRoute
Route
public class LowercaseRoute : Route { public LowercaseRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { } public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler) { } public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler) { } public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler) { } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { VirtualPathData path = base.GetVirtualPath(requestContext, values); if (path != null) path.VirtualPath = path.VirtualPath.ToLowerInvariant(); return path; } }
然后修改 Global.asax.cs 的 RegisterRoutes方法
RegisterRoutes
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add(new LowercaseRoute("{controller}/{action}/{id}", new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }), new MvcRouteHandler())); //routes.MapRoute( // "Default", // Route name // "{controller}/{action}/{id}", // URL with parameters // new { controller = "Home", action = "Index", id = "" } // Parameter defaults //); }
但是我想知道一种使用路线的方法。
如果使用 UrlHelper 生成链接,只需将操作和控制器的名称指定为小写:
itemDelete.NavigateUrl = Url.Action("delete", "photos", new { key = item.Key });
结果为:/media/photos/delete/64(即使我的控制器和操作是 pascal case)。
通过将此类添加为 RouteCollection 的扩展,您可以继续使用 MapRoute 语法:
public static class RouteCollectionExtension { public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults) { return routes.MapRouteLowerCase(name, url, defaults, null); } public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults, object constraints) { Route route = new LowercaseRoute(url, new MvcRouteHandler()) { Defaults = new RouteValueDictionary(defaults), Constraints = new RouteValueDictionary(constraints) }; routes.Add(name, route); return route; } }
现在您可以在应用程序的启动程序中使用“ MapRouteLowerCase”而不是“ MapRoute”:
public void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // Url shortcuts routes.MapRouteLowerCase("Home", "", new { controller = "Home", action = "Index" }); routes.MapRouteLowerCase("Login", "login", new { controller = "Account", action = "Login" }); routes.MapRouteLowerCase("Logout", "logout", new { controller = "Account", action = "Logout" }); routes.MapRouteLowerCase( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); }
使用 System.Web.Routing 4.5,您可以直接通过设置 RouteCollection 的 LowercaseUrls 属性来实现这一点:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.LowercaseUrls = true; routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
另外,假设您这样做是出于 SEO 的原因,您希望将传入的 URL 重定向为小写(正如本文的许多链接中所说的那样)。
protected void Application_BeginRequest(object sender, EventArgs e) { //You don't want to redirect on posts, or images/css/js bool isGet = HttpContext.Current.Request.RequestType.ToLowerInvariant().Contains("get"); if (isGet && !HttpContext.Current.Request.Url.AbsolutePath.Contains(".")) { //You don't want to modify URL encoded chars (ex.: %C3%8D that's code to Í accented I) to lowercase, than you need do decode the URL string urlLowercase = Request.Url.Scheme + "://" + HttpUtility.UrlDecode(HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath); //You want to consider accented chars in uppercase check if (Regex.IsMatch(urlLowercase, @"[A-Z]") || Regex.IsMatch(urlLowercase, @"[ÀÈÌÒÙÁÉÍÓÚÂÊÎÔÛÃÕÄËÏÖÜÝÑ]")) { //You don't want to change casing on query strings urlLowercase = urlLowercase.ToLower() + HttpContext.Current.Request.Url.Query; Response.Clear(); Response.Status = "301 Moved Permanently"; Response.AddHeader("Location", urlLowercase); Response.End(); } } }
如果您碰巧使用 ASP.NET Core,那么您可能应该看一下 这个:
将以下代码行添加到 Startup类的 ConfigureServices方法。 services.AddRouting(options => options.LowercaseUrls = true);
将以下代码行添加到 Startup类的 ConfigureServices方法。
Startup
ConfigureServices
services.AddRouting(options => options.LowercaseUrls = true);