Как я могу иметь строчные маршруты в ASP.NET MVC?
Как я могу, если возможно, указать нижний регистр, плюс подчеркивание, маршруты в ASP.NET MVC? Чтобы я имел /dinners/details/2
вызов DinnersController.Details(2)
и, если возможно, /dinners/more_details/2
вызов DinnersController.MoreDetails(2)
?
Все это при использовании шаблонов, таких как {controller}/{action}/{id}
.
Ответы
Ответ 1
С помощью System.Web.Routing 4.5 вы можете реализовать это просто, установив свойство LowercaseUrls для RouteCollection:
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(".") == false)
{
string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
{
//You don't want to change casing on query strings
lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", lowercaseURL);
Response.End();
}
}
}
Ответ 2
Эти два учебника помогли мне, когда я хотел сделать то же самое и хорошо работать:
http://www.coderjournal.com/2008/03/force-mvc-route-url-lowercase/
http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/
EDIT: для проектов с областями вам необходимо изменить метод 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);
}
Ответ 3
Если вы используете UrlHelper для создания ссылки, вы можете просто указать имя действия и контроллера как строчные:
itemDelete.NavigateUrl = Url.Action("delete", "photos", new { key = item.Key });
Результаты в:/media/photos/delete/64 (хотя мой контроллер и действие - это pascal case).
Ответ 4
Я нашел это в Nick Berardis 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
//);
}
Мне бы хотелось узнать способ использования маршрутов. MapRoute...
Ответ 5
Вы можете продолжить использовать синтаксис MapRoute, добавив этот класс в расширение для RouteCollection:
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
);
}
Ответ 6
Если вам удалось использовать ASP.NET Core, вам, вероятно, следует взглянуть на this:
Добавьте следующую строку в метод ConfigureServices
класса Startup
.
services.AddRouting(options => options.LowercaseUrls = true);
Ответ 7
На самом деле у этого есть два ответа:
- Вы уже можете это сделать: механизм маршрута делает сравнение без учета регистра. Если вы наберете строчный маршрут, он будет перенаправлен на соответствующий контроллер и действие.
- Если вы используете элементы управления, которые генерируют маршруты (ActionLink, RouteLink и т.д.), они будут создавать ссылки со смешанным случаем, если вы не отмените это поведение по умолчанию.
Вы сами по себе для подчеркивания, хотя...
Ответ 8
Не могли бы вы использовать атрибут ActionName?
[ActionName("more_details")]
public ActionResult MoreDetails(int? page)
{
}
Я не думаю, что дело имеет значение. More_Details, more_DETAILS, mOrE_DeTaILs в URL-адресе приведет вас к одному и тому же действию контроллера.