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

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

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

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

Для создания маршрутов можно использовать метод MapRoute. Например:

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

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

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

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

        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 = UrlParameter.Optional });.

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

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

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

Итак, добавим в папку 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 = UrlParameter.Optional }

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

routes.MapRoute(name: "Default", url: "Ru{controller}/{action}/{id}", defaults: new { id = UrlParameter.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 = UrlParameter.Optional });

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

При отправлении приложению запроса типа http://localhost:49326/RuHome/Index, если у нас в приложении не определен контроллер RuHomeController, приложение вернет ошибку. Почему? Потому система маршрутизации пытается сопоставить запрос сначала с первым маршрутом. Если запрос не соответствует первому маршруту - тогда со вторым и так далее по списку маршрутов, пока не найдет нужный. В данном случае входящий запрос соответствует и первому, и второму маршрутам. Однако первый маршрут будет искать контроллер по имени 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 = UrlParameter.Optional });
    routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = UrlParameter.Optional });
}

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

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

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

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

Чтобы получить переданные значения для параметров маршрута, мы можем воспользоваться объектом RouteData. Например, если у нас определен стандартный маршрут routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { id = UrlParameter.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 = UrlParameter.Optional, name = UrlParameter.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