Маршрутизация

Определение маршрутов

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2015

В предыдущих главах мы так или иначе сталкивались с маршрутизацией. Например, при обращении к некоторому действию контроллера мы набирали в адресной строке браузера 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 данного маршрута.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850