如何在 ASP.NET MVC 中使用小写字母和下划线(如果可能)?所以我会/dinners/details/2
打电话DinnersController.Details(2)
,如果可能的话,/dinners/more_details/2
打电话DinnersController.MoreDetails(2)
?
所有这一切,同时仍然使用像{controller}/{action}/{id}
.
如何在 ASP.NET MVC 中使用小写字母和下划线(如果可能)?所以我会/dinners/details/2
打电话DinnersController.Details(2)
,如果可能的话,/dinners/more_details/2
打电话DinnersController.MoreDetails(2)
?
所有这一切,同时仍然使用像{controller}/{action}/{id}
.
使用 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();
}
}
}
当我想做同样的事情并很好地工作时,这两个教程很有帮助:
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);
}
如果你碰巧使用 ASP.NET Core,你可能应该看看这个:
将以下行添加到类的
ConfigureServices
方法中Startup
。services.AddRouting(options => options.LowercaseUrls = true);
如果您使用 UrlHelper 生成链接,您可以简单地将操作和控制器的名称指定为小写:
itemDelete.NavigateUrl = Url.Action("delete", "photos", new { key = item.Key });
结果:/media/photos/delete/64(即使我的控制器和操作是帕斯卡案例)。
我在Nick Berardi 的 Coder Journal中找到了这个,但它没有关于如何实现LowercaseRoute
该类的信息。因此,在此处重新发布附加信息。
首先将Route
类扩展到LowercaseRoute
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;
}
}
然后修改RegisterRoutes
Global.asax.cs的方法
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
//);
}
但是,我想知道一种使用 routes.MapRoute 的方法...
您可以通过将此类添加为 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
);
}
这实际上有两个答案:
不过,下划线是你自己的……
你可以使用 ActionName 属性吗?
[ActionName("more_details")]
public ActionResult MoreDetails(int? page)
{
}
我认为案件不重要。URL 中的 More_Details、more_DETAILS、mOrE_DeTaILs 都将您带到同一个 Controller Action。