Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Одним из нововведений MVC 5 стала такая функциональность как атрибуты маршрутизации (attribute routing). Данные атрибуты позволяют сопоставить определенный маршрут с методом контроллера. Например, у нас есть такой метод в контроллере HomeController:
public string Test(int id, string name) { return id.ToString() + ". " + name; }
Ему мог бы соответствовать следующий маршрут, определенный в файле RouteConfig.cs:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default2", url: "{id}/{name}", defaults: new { controller = "Home", action = "Test"}, constraints: new { id="\d+"} ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
Параметр constraints: new { id="\d+"}
ограничивает первый сегмент строки запроса числами, таким образом, у нас не будет конфликта между двумя маршрутами. То есть запрос вида
http://localhost:6392/2/volga будет сопоставляться с первым маршрутом, а если вместо числа 2 будет идти строка - то со вторым.
Но атрибуты маршрутизации позволяют не определять дополнительный маршрут, а указать сопоставление прямо в коде контроллера:
[Route("{id:int}/{name}")] public string Test(int id, string name) { return id.ToString() + ". " + name; }
Кроме того, нам надо изменить код в файле RouteConfig.cs следующим образом:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
Здесь вместо определения маршрута мы используем метод routes.MapMvcAttributeRoutes();
, который подключает в систему маршрутизации приложения
функциональность атрибутов маршрутизации.
Мы также можем явно указать имя контроллера или метода или параметра в атрибуте: [Route("Home/{id:int}/{name}")]
. Данный маршрут
будет соответствовать запросу Home/4/somename
В определении сегмента id мы использовали ограничение, чтобы явно указать, что этот сегмент должен представлять целое число: id:int
. Кроме
int мы можем задать еще ряд ограничений по типу:
alpha: соответствует только алфавитным символам латинского алфавита. Например, {id:alpha}
bool: соответствует логическлму значению. Например, {id:bool}
datetime: соответствует значению DateTime. Например, {id:datetime}
decimal: соответствует значению decimal. Например, {id:decimal}
double: соответствует значению double. Например, {id:double}
float: соответствует значению float. Например, {id:float}
length: соответствует строке определенной длины, либо ее длина должна быть в определенном диапазоне.
Например, {id:length(5)}
или {id:length(5, 15)}
long: соответствует значению long. Например, {id:long}
max: соответствует значению int, которое не больше значения max. Например, {id:max(99)}
.
Аналогичным образом действует ограничение min, только оно указывает на минимально допустимое значение сегмента.
maxlength: соответствует строке, длина которой не больше определенного значения. Например, {id:maxlength(20)}
.
Аналогичным образом работает ограничение minlength, указывая на минимально допустимую длину строки
range: указывает на диапазон, в пределах которого должно находиться значение сегмента. Например, {id:range(5, 20)}
regex: соответствует регулярному выражению. Например, {id:regex(^\d{3}-\d{3}-\d{4}$)}
Как и при определении маршрута, мы можем задать значения для параметров по умолчанию:
[Route("{id:int}/{name=volga}")] public string Test(int id, string name) { return id.ToString() + ". " + name; }
Так, если строка запроса не будет содержать последний параметр, то вместо него будет использоваться строка "volga".
Выше приводился пример атрибута маршрутизации с название контроллера в начале: [Route("Home/{id:int}/{name}")]
. Но если у нас вдруг
есть несколько подобных действий, обращение к которым должно начинаться с "Home", то удобно использовать префиксы:
[RoutePrefix("home")] public class HomeController : Controller { [Route("{id:int}/{name}")] public string Test(int id, string name) { return id.ToString() + ". " + name; } [Route("{id:int}")] public string Sead(int id) { return id.ToString(); } [Route("~/lol/twit/{id:int}")] public string Twit(int id) { return id.ToString(); } }
Теперь запрос к обоим методам должен начинаться с Home: "Home/5/fds" или "Home/5". При этом префикс не обязательно должен совпадать с именем контроллера, а может иметь любое значение.
Последний маршрут устраняет действие префикса с помощью знака тильды (~) в начале маршрута. И чтобы к этому методу обратиться, надо будет использовать запрос http://localhost:6392/lol/twit/2.