Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
В предыдущих главах мы так или иначе сталкивались с маршрутизацией. Например, при обращении к некоторому действию контроллера мы набирали
в адресной строке браузера http://localhost:3456/Home/Index, где Home - имя контроллера без
префикса Controller, а Index - имя метода действия этого контроллера. Если метод
Index
принимал бы какой-нибудь параметр, например, типа int
: public ActionResult Index(int Id)
, то мы могли обратиться к этому методу и
передать значение в его параметр с помощью следующей строки: http://localhost:3456/Home/Index/5. В этом плане все очень просто.
Но мы не говорили еще о том, почему мы должны прописывать маршрут именно так, и как мы собственно можем управлять маршрутами.
Рассмотрим механизм определения маршрутов. В ASP.NET MVC 5 все определения маршрутов находятся в файле RouteConfig.cs, который располагается в проекте в папке App_Start. Если мы на него посмотрим, то увидим настройки маршрута по умолчанию:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace Mvc5RoutesApp { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }
Установкой маршрутов занимается статический метод RegisterRoutes
. Однако на этом определение маршрутов не заканчивается, так как нам еще надо вызвать этот метод
в приложении при запуске. Это производится в файле Global.asax в методе Application_Start:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }
Вызов метода RouteConfig.RegisterRoutes(RouteTable.Routes);
как раз и производит регистрацию маршрутов в приложении.
Теперь разберем определение маршрута по умолчанию в файле RouteConfig.cs. Первая строка routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
отключает обработку запросов
для некоторых файлов, например с расширением *.axd (WebResource.axd).
Далее идет собственно определение маршрута по умолчанию. Метод routes.MapRoute
выполняет сопоставление маршрута запросу.
В перегруженных версиях данного метода мы можем задать дополнительные параметры сопоставления.
Разберем параметры метода. Вначале с помощью свойства name задается имя маршрута - Default.
Второй параметр - url
задает шаблон строки запроса или шаблон Url, с которым будет сопоставляться данный маршрут.
Шаблон URL включает в себя несколько сегментов, которые заключены в фигурные скобки. В данном случае сегмент представляет часть запроса, которая находится между слешами. Каждый такой сегмент шаблона содержит параметр. Эти параметры называются параметрами URL. В данном случае это параметры controller, action и id. Но вообще параметры могут иметь различные имена, включающие любые алфавитно-цифровые символы.
При получении запроса механизм маршрутизации парсит строку URL и помещает значения маршрута в словарь - в объект RouteValueDictionary
,
доступный через контекст приложения RequestContext
. В качестве ключей в нем применяются имена параметров URL, а соответствующие
сегменты URL выступают в качестве значений. Например, у нас есть следующий URL запроса: http://localhost/Home/Index/5,
то в этом случае образуются следующие пары ключей и значений в словаре RouteValueDictionary
:
Параметр | Значение |
controller | Home |
action | Index |
id | 5 |
Третий параметр метода routes.MapRoute - defaults
определяет значения по умолчанию для маршрута. Например, если вдруг в строке запрос указаны не все параметры,
а сам запрос, к примеру, идет по адресу http://localhost/, то система маршрутизации вызовет метод Index контроллера Home, как указано в параметре defaults
.
Также, если мы не укажем метод контроллера, например, http://localhost/Home/, также будет вызван метод Index контроллера Home.
Поэтому если мы захотим, к примеру, чтобы у нас по умолчанию клиент обращался не к методу Index контроллера HomeController, а, например, к методу Show контроллера BookController, то мы можем соответственно изменить значения данного параметра:
defaults: new { controller = "Book", action = "Show", id = UrlParameter.Optional }
Последний параметр объявлен как необязательный id = UrlParameter.Optional
, поэтому, если он не указан в строке запроса, он не будет учитываться
и передаваться в словарь параметров RouteValueDictionary
.
Например, запрос http://localhost/Home/Create/3 вызовет метод Create контроллера HomeController, передав в этот метод
в качестве параметра число 3. В то же время запрос http://localhost/Home/Create/ также вызовет метод Create контроллера HomeController,
хотя последний параметр в нем не указан.
Таким образом, настройки по умолчанию позволяют нам не указывать в строке запроса полностью название контроллера и его метода. Но в случае, если такие настройки не заданы, мы должны определять в строке запроса контроллер и его метод. Например, изменим установку маршрутов в файле RouteConfig.cs следующим образом:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}" ); } }
Теперь обратимся к нашему приложению, набрав в строке браузера только адрес сайта, например, http://mysyte.com/. В этом случае мы получим информацию об ошибке. Ошибка будет состоять в том, что теперь нам надо полностью набирать в строке запроса адрес ресурса. Поэтому следующий адрес http://mysyte.com/Home/Index будет нормально работать (если, конечно, в приложении определен контроллер Home с методом Index и соответствующим ему представлением).
И если мы теперь перейдем по адресу http://localhost/Home/, как мы это делали выше, то опять получим ошибку, так как в строке запроса указан только один сегмент. А в определении маршрута у нас указано два сегмента - {controller}/{action}. Если для параметров не определены значения по умолчанию, то строка запроса должна иметь такое же число сегментов, для которых не определены значения по умолчанию.
В то же время если запрос будет состоять из трех сегментов, например, http://localhost/Home/Index/1, то мы также получим ошибку, потому что число сегментов в запросе больше числа, определенного в шаблоне URL данного маршрута.