Работа с маршрутами

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

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

Создание новых маршрутов

Создать свой маршрут мы можем, например, как было уже показано, с помощью метода MapRoute. Например:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        //............................
        routes.MapRoute(
            name: "newRoute",
            url: "{controller}/{action}"
        );
    }
}

Либо мы можем создать объект Route и потом добавить его в коллекцию маршрутов RouteCollection. Определим два маршрута:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}"
        );

        Route newRoute = new Route("{controller}/{action}", new MvcRouteHandler());
        routes.Add(newRoute);
    }
}

Итак, здесь определены два маршрута. Первый - маршрут Default сопоставляется с запросами, имеющими три сегмента. Второй - newRoute сопоставляется с запросами, имеющими только два сегмента. В итоге вызов http://localhost:5555/Home/Index/1 будет соответствовать первому маршруту, так как в нем определено три сегмента. А вызов http://localhost:5555/Home/Index - второму маршруту. Вызов http://localhost:5555/Home не будет соответствовать ни одному маршруту, так как у нас не определен маршрут, принимающий только один сегмент в шаблоне URL.

Правда, ситуация с этими двумя запросами в большей степени является искусственной, так как мы можем совместить их, просто определив параметр id как необязательный: routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });.

При передаче значений по умолчанию для параметров мы должны учитывать позицию параметра. Движок маршрутизации использует значение по умолчанию только тогда, когда все последующие параметры также имеют значения по умолчанию. Так, если мы зададим следующий маршрут: routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { action = "Index" });, то запрос, содержащий два сегмента, например, Home/2 не будет сопоставляться с данным маршрутом. Поэтому нам надо в данном случае указать значение по умолчанию также и для параметра id.

Сопоставление запросов с файлами на диске

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

Итак, добавим в папку Content проекта новую html-страницу и назовем ее, например, Welcome.html

Определим какое-нибудь простенькое содержание страницы. Теперь мы можем обращаться к этой странице напрямую через запрос Content/Welcome.html.

Использование префиксов в строке запроса

Сегменты строки запроса необязательно должны нести только значения для параметров, определенных в маршруте. Мы также можем использовать различные префиксы в строке запроса и соответствующим образом настроить маршрут для обработки подобных запросов. Например, мы хотим, чтобы запрос содержал префикс Ru: http://localhost:49326/Ru/Home/Index/1. Тогда обрабатывающий этот запрос маршрут может выглядеть следующим образом:

routes.MapRoute(name: "Default", url: "Ru/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional }

Кроме того, мы можем добавлять префиксы не в качестве отдельного сегмента, а к самому сегменту:

routes.MapRoute(name: "Default", url: "Ru{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional }

В этом случае строка запроса, соответствующая данному маршруту, может выглядеть так: http://localhost:49326/RuHome/Index

Порядок определения новых маршрутов

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

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });

    routes.MapRoute( name: "Default2", url: "Ru{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
}

Если мы отправим приложению запрос типа http://localhost:49326/RuHome/Index и если у нас в приложении не определен контроллер RuHome, то приложение вернет ошибку. Почему? Потому система маршрутизации пытается сопоставить запрос сначала с первым маршрутом. Если запрос не соответствует первому маршруту - тогда со вторым и так далее по списку маршрутов, пока не найдет нужный. В данном случае входящий запрос соответствует и первому и второму маршрутам. Однако первый маршрут будет искать контроллер по имени RuHomeController и, не найдя его, вернет ошибку. Поэтому чтобы подобная ситуация не произошла, надо сначала определить маршрут Default2, который более специфичен и не конфликтует с первым:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
	routes.MapRoute( name: "Default2", url: "Ru{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
    routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
}

Кроме того, мы можем использовать префиксы в качестве псевдонимов для контроллера и его метода:

routes.MapRoute( name: "Default2", url: "Store/Buy", defaults: new { controller = "Home", action="Index" } );

Здесь для контроллера Home мы используем псевдоним Store, а для действия Index - псевдоним Buy. В итоге данный маршрут будет сопоставляться с таким запросом, как Store/Buy. А система маршрутизации будет обращаться по такому запросу к методу Index контроллера Home.

Получение переданных параметров

Чтобы получить переданные значения для параметров маршрута, мы можем воспользоваться объектом RouteData. Например, если у нас определен стандартный маршрут routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });, то мы можем получить значение параметра controller следующим образом:

public string Index()
{
    string controller = RouteData.Values["controller"].ToString();
    return controller;
}

Значения, передаваемые в качестве дополнительных значений, например, для параметра id, мы можем извлекать из самого параметра метода:

public ActionResult Index(int id)
{
    ViewBag.OldId = id;
	//или так
	// ViewBag.OldId = RouteData.Values["id"];
    return View();
}

Передача различного числа параметров в запросе

Ранее мы ограничивались только тремя сегментами. Но если у нас скажем метод принимает два и более параметров:

public ActionResult Index(int id=1, string name="")
{
    ViewBag.Name = name;
    return View();
}

То мы просто можем добавить в маршрут нужное нам количество параметров:

routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}/{name}", defaults: new { id = RouteParameter.Optional, name = RouteParameter.Optional });

Тогда данный маршрут будет обрабатывать запрос типа Home/Index/1/name, что эквивалентно следующей строке запроса: Home/Index?id=1&name=name

Кроме того, мы можем обозначить любое количество сегментов в запросе, чтобы не быть жестко привязанным к числу сегментов с помощью параметра {*catchall}:

routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}/{*catchall}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional});

Теперь мы можем обрабатывать запросы с любым количеством сегментов:

Запрос

Параметры запроса

mysyte.com

controller=Home

action=Index

mysyte.com/Book

controller=Book

action=Index

mysyte.com/Book/Show

controller=Book

action=Show

mysyte.com/Book/Show/2

controller=Book

action=Show

id=2

mysyte.com/Book/Show/2/Oldedition

controller=Book

action=Show

id=2

catchall=Oldedition

mysyte.com/Book/Show/2/Oldedition/1960

controller=Book

action=Show

id=2

catchall=Oldedition/1960

После получения значения для параметра catchall мы сами должны обработать его и получить уже значения для отдельных сегментов.

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