ЖАНРЫ

Шрифт:

При создании маршрута строковый параметр Url определяет шаблон маршрута, который, как правило, задает некоторую группу возможных клиентских запросов. Следует учитывать, что при наличии нескольких маршрутов механизм маршрутизации ASP.NET всегда выбирает самый первый из них — тот, что был добавлен в таблицу маршрутизации первым.

Как мы уже говорили, по умолчанию MVC Framework создает один-единственный маршрут с именем Default и шаблоном {controller}/{action}/{id}. Этот маршрут хорош тем, что он один позволяет обрабатывать большую часть возможных пользовательских запросов. По сути такой шаблон говорит о том, что данный маршрут определяет все запросы с вложениями до третьего уровня, т. е. этот маршрут обработает и http://sample.domain/level1/ и http://sample.domain/level1/level2/,

и http://sample.domain/level1/level2/level3/, где level1, level2 и level3 могут принимать любые значения. На самом деле это очень большое количество возможных запросов и на практике один маршрут Default покрывает все требования разработчиков к маршрутизации.

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

routes.MapRoute(

"AccountLogOn",

"LogOn",

new { controller = "Account", action = "LogOn" }

);

routes.MapRoute(

"Home",

"{action}",

new { controller = "Home", action = "Index" }

);

Первый вызов MapRoute создает маршрут под наименованием AccountLogOn, шаблон которого четко соответствует только одному возможному клиентскому запросу http://sample.domain/Logon. Второй вызов создает маршрут Home более широкого определения. Под этот маршрут попадают все клиентские запросы вида http://sample.domain/Home/{action}.

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

public ActionResult SomeAction

{

return RedirectToRoute("AccountLogOn");

}

Другим видимым преимуществом этого маршрута является то, что согласно ему клиентский запрос не обязательно должен содержать в себе наименование контроллера. Таким образом, путь http://some.domain/Account/LogOn уменьшается до http://some.domain/LogOn, что придает ссылкам вебприложения более компактный вид. Компактность строк запросов может играть свою роль в случае, когда в большом веб-приложении используются десятки контроллеров с массой действий и параметров.

Значения параметров маршрута по умолчанию и свойство Defaults

Свойство Defaults определяет набор параметров, сопоставляемых параметрам маршрута по умолчанию, в случае, когда URL строки запроса их не содержит. Рассмотрим для примера маршрут {controller}/{action}/{id}, создаваемый в проектах MVC Framework по умолчанию. При его создании свойство Defaults было инициализировано с помощью метода расширения MapRoute следующим значением:

new { controller = "Home", action = "Index", id = "" }

На практике это будет означать, что механизм MVC Framework одинаково обработает запросы http://sample.domain/Home/Index/, http://sample.domain/Home/ и http://sample.domain/. Все эти запросы приведут к вызову действия Index в контроллере HomeController. Это стало возможным, поскольку были определены значения по умолчанию для параметров маршрута controller и action. В связи с этим URL http://sample.domain/ при сопоставлении маршруту дополучит часть параметров из словаря Defaults, став, таким образом, равнозначным запросу http://sample.domain/Home/Index/.

Ограничения параметров маршрута и свойство Constraints

Свойство Constraints определяет набор параметров, которые служат ограничителями для параметров маршрута. Рассмотрим пример: при создании проекта вы определяете маршрут, один из параметров которого указывает логин пользователя. Согласно правилам вашего ресурса логин пользователя не может содержать менее 4 символов в виде букв и цифр. Поэтому все запросы, которые попадают под ваш маршрут

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

Чтобы решить задачу с ограничением на длину имени логина в запросе, нужно определить следующее ограничение в свойстве Constraints при создании маршрута:

var constraint = new RouteValueDictionary {

{"user", "\\w{4,}"}

};

routes.Add(new Route(

"{controller}/{action}/{user}/",

defaults,

constraint,

null,

new MvcRouteHandler

));

Ограничение определяется как элемент словаря RouteValueDictionary, где ключом является имя параметра, а значением регулярное выражение, описывающее правило для параметра. В данном случае регулярное выражение \w{4,} предполагает, что строка должна содержать буквы и цифры в размере от 4 элементов.

После такого определения маршрута, если вы попытаетесь обратиться по следующему адресу http://sample.domain/Home/Index/foo, вы получите стандартное сообщение браузера о возвращенной сервером ошибке с кодом 404 "Страница не найдена".

Ранее в этой главе мы рассмотрели ограничения параметров как коллекцию регулярных выражений в свойстве Constraints класса Route. Однако существует еще один, альтернативный, способ создания маршрута на базе интерфейса iRouteConstraint. Он также описан в этой главе. Вместо того чтобы добавлять в коллекцию Constraints строки с регулярными выражениями, можно воспользоваться интерфейсом IRouteConstraint и реализовать класс, который будет выполнять проверку параметров на соответствие условиям. Добавляется такой класс похожим на обычный способом:

routes.MapRoute("Default",

"{controller}/{action}/{user}",

new {controller = "Home",

action = "Index",

id = ""},

new {user = new SampleConstraint}

);

Здесь SampleConstraint — это класс, который реализует интерфейс IRouteConstraint.

Параметры маршрута и свойство DataTokens

В механизме маршрутизации ASP.NET при создании маршрута можно указать набор параметров DataTokens. Используя DataTokens, разработчик может передать в маршрут набор данных, которые позднее будут использованы пользовательским вариантом обработчика маршрута при сопоставлении клиентского запроса маршруту. Иными словами, DataTokens помогает определить больше данных для маршрутов в случае, когда пользователь сам определяет обработчик маршрута. В MVC Framework каждому маршруту сопоставляется уже готовый обработчик MvcHandler. Поэтому надобность в пользовательских параметрах, передаваемых через DataTokens, отпадает, очевидно, что эти данные MvcHandler использовать не сможет. В связи с тем, что данные DataTokens в проектах MVC Framework по умолчанию не нужны, в методе расширения MapRoute создание такого набора вовсе отсутствует.

Однако есть исключение, делающее свойство DataTokens экземпляра маршрута полезным даже для проектов MVC Framework. Дело в том, что фабрика контроллеров по умолчанию проверяет DataTokens на наличие параметра Namespaces, от которого в дальнейшем зависит, какие контроллеры могут быть выбраны для инстанцирования.

Параметр Namespaces может содержать строки в виде перечисления типа iEnumerable<string>. Когда фабрика контроллеров находит такой параметр в свойстве DataTokens, она предполагает, что в нем перечислены наименования пространств имен, в которых можно искать контроллеры для инстанцирования в ответ на клиентский запрос.

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

Для того чтобы указать определенный набор пространств имен при создании маршрута, необходимо проделать примерно такие действия:

Поделиться с друзьями: