Введение в маршрутизацию
Вместо того, чтобы связывать URL с физическим файлом на диске, ASP.NET MVC представляет инфраструктуру маршрутизации URL, которая позволяет соотносить URL с действием контроллера без необходимости, чтобы на сервере существовал физический файл как конечная точка URL. В этом разделе мы рассмотрим структуру маршрутизации по умолчанию, которая существует в новых проектах MVC, а также то, как понятие роута соотносится с понятиями контроллера и действия.
Роуты по умолчанию
При создании нового приложения ASP.NET MVC, шаблон проекта по умолчанию создает метод под названием RegisterRoutes
в файле Global.asax
. Этот метод отвечает за настройку роутов для приложения и первоначально определяется с двумя роутами: роутом, который не следует проверять на соответствия (ignore route) и роутом по умолчанию, который сопоставим с {controller}/{action}/{id}
, как показано здесь. api-роут тут опущен и рассматривается в главе 23.
Листинг 9-1: Роут по умолчанию
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
Строка 2:
IgnoreRoute
Строка 4: Имя роута
Строка 5: URL с параметрами
Строки 6-7: Значения по умолчанию для параметров
Строка 12: Регистрация роутов при запуске приложения
Роуты определяются вызовом метода MapRoute
, для которого существует несколько перегруженных вариантов. В данном случае роут по умолчанию настраивается вызовом перегруженного варианта, который принимает три аргумента. Первым является имя роута ("Default
"). Второй – это шаблон URL, в соответствии с которым нужно создавать URL. Сейчас для него определены три сегмента - controller
, action
и id
. Третий аргумент представляет собой анонимный тип, который определяет значения по умолчанию для этих сегментов. Давайте рассмотрим пример того, как может быть использован этот роут.
Если пользователь посетил URL-адрес http://example.com/users/edit/5
, этот адрес соответствовал бы роуту по умолчанию, поскольку он имеет три сегмента, как показано на рисунке 9-1.
Рисунок 9-1: Как сегменты URL соотносятся с роутом

В этом случае строка users
соотносится с параметром controller
, edit
соотносится с параметром action
и 5
соотносится с параметром id
. Так как это полностью соответствует нашему роуту, платформа MVC попытается найти класс UsersController
и вызвать метод Edit
, и передаст значение 5
в параметр id
. Обратите внимание, что если контроллер или действие не могут быть найдены, платформа выведет ошибку 404.
Контроллер, который соответствует данному примеру, может быть определен следующим образом:
public class UsersController : Controller
{
public ActionResult Edit(int id)
{
return View();
}
}
По соглашению, платформа пытается соотнести параметры роута controller
и action
с классом и методом.
Параметры по умолчанию, добавленные к определению роута в листинге 9-1, означают, что URL не должен в точности совпадать с трехсегментным шаблоном URL. Если вы укажете Home
как контроллер по умолчанию и Index
как действие по умолчанию, и сегмент контроллера будет опущен, роутом по умолчанию станет HomeController
. Аналогичным образом, если не указан сегмент действия, роут по умолчанию будет искать действие Index
. Значение по умолчанию UrlParameter.Optional
для параметра id
означает, что роут может быть найден независимо от того, указан третий сегмент или нет. В таблице 9-1 показаны несколько примеров URL-адресов, которые могут соответствовать роуту по умолчанию. В дополнение к роуту по умолчанию, метод RegisterRoutes
содержит вызов к IgnoreRoute
.
Таблица 9-1: URL-адреса, которые соотносятся с роутом по умолчанию
URL | Параметры роута | Выбранный метод действия |
http://example.com/Users/Edit/5 |
Controller = Users , Action = Edit , id = 5 |
UsersController.Edit(5) |
http://example.com/Users/Edit |
Controller = Users , Action = Edit |
UsersController.Edit() |
http://example.com/Users |
Controller = Users , Action = Index |
UsersController.Index() |
http://example.com |
Controller = Home , Action = Index |
HomeController.Index() |
Как и метод MapRoute
, IgnoreRoute
следует шаблону URL, но он также гарантирует, что любой URL-адрес, который соответствуют шаблону, не обрабатывается инфраструктурой маршрутизации. В этом случае шаблон {resource}.axd/{*pathInfo}
гарантирует, что все URL, содержащие расширение файла .axd
, не обрабатываются движком маршрутизации. Это необходимо, чтобы любые пользовательские обработчики HTTP (с расширением .axd
) обрабатывались корректно и не перехватывались движком маршрутизации. Звездочка перед параметром pathInfo
является универсальным (catch-all) параметром, который соответствует любой строке (включая слеши, которые обычно используются для установления границ сегментов URL). Мы рассмотрим catch-all роуты далее.
Такой тип маршрутизации, где URL сопоставляется с действием контроллера, известен как входящая маршрутизация, но есть и другой тип маршрутизации - исходящая маршрутизация, которая может генерировать URL из параметров роута, таких как контроллер и действие.
Входящая и исходящая маршрутизация
Инфраструктура маршрутизации разбивает URL на сегменты, исходя из логики приложения. Она должна владеть двумя направлениями:
- Входящая маршрутизация - сопоставление запросов с контроллером, действием и любыми дополнительными параметрами (см. рисунок 9-2).
- Исходящая маршрутизация - построение URL-адресов, которые соответствуют схеме URL из контроллера, действия и любых дополнительных параметров (см. рисунок 9-3).
Входящая маршрутизация, как показано на рисунке 9-2, описывает, как URL-адрес вызывает действие контроллера. HTTP-запрос поступает в конвейер ASP.NET и передается по роутам, зарегистрированным в приложении ASP.NET MVC. Каждый роут имеет возможность обработать запрос, и затем соответствующий роут укажет, какой контроллер и действие будут использоваться.
Рисунок 9-2: Входящая маршрутизация принимает HTTP-запрос и соотносит части URL с контроллером и действием.

Исходящая маршрутизация, как показано на рисунке 9-3, описывает механизм генерации URL для ссылок и других элементов на сайте, где используются зарегистрированные роуты. Когда система маршрутизации выполняет обе эти задачи, схема URL может быть по-настоящему независимой от логики приложения. Если мы никогда не обходим схему URL при построении ссылок в представлении, ее довольно просто изменить независимо от логики приложения.
Рисунок 9-3: Исходящая маршрутизация генерирует соответствующие URL-адреса из заданного набора данных о роуте (обычно контроллера и действия).

Теперь, когда мы рассмотрели основы механизма маршрутизации URL, давайте обратим внимание на то, как построить значимую схему URL для нашего приложения.