Генерация ссылок

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

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

Кроме хелперов форм и шаблонных хелперов в ASP.NET Core MVC также имеется ряд методов, которые применяются для генерации исходящих адресов в приложении, например, при выводе их в представлении.

Наиболее простой способ вывода адреса является использование анкора - элемента a:

<a href="~/Home/Index/3" />

Но также мы можем использовать специальные хелперы рендеринга - Html.ActionLink и Html.RouteLink.

Html.ActionLink

Хелпер ActionLink создает гиперссылку на действие контроллера. Если мы создаем ссылку на действие, определенное в том же контроллере, то можем просто указать имя действия:

@Html.ActionLink("О сайте", "About")

Что создаст вам следующую разметку:

<a href="/Home/About">О сайте</a>

Если необходимо указать ссылку на действие из другого контроллера, то в хелпере ActionLink в качестве третьего аргумента имя контроллера. Например, ссылка на действие List контроллера Book будет создаваться так:

@Html.ActionLink("Список книг", "List", "Book")

Кроме того, если у нас в некотором методе Index контроллера HomeController определено несколько параметров:

public class HomeController : Controller
{
    public IActionResult GetUser(string name="Тоm", int id = 1)
	{
            return Content($"{id}. {name}");
	}
	// остальные методы
}

То перегруженная версия хелпера ActionLink позволяет передать параметр объекта (обычно анонимный тип) для параметра routeValues. Среда выполнения принимает свойства объекта и использует их для создания значений маршрутизации (имена свойств становятся именами параметров маршрута, а значения свойств представляют значения параметра маршрута). Создадим ссылку для вышеопределенного действия контроллера:

@Html.ActionLink("Пользователь 10", "GetUser", "Home", new { id = 10 }, null)

@Html.ActionLink("Alice", "GetUser", "Home", new { name = "Alice", id = 5 }, null)

Последний параметр в данном хелпере является параметром htmlAttributes. Мы можем использовать этот параметр для установки значения атрибута элемента HTML. В данном случае передается значение null (то есть никаких атрибутов не устанавливается).

Теперь попробуем передать атрибуты, например, установить атрибуты id и class:

@Html.ActionLink("Sam", "GetUser", "Home", new { name = "Sam", id = 12 }, new { id = "sam", @class = "link" })

Сгенерированная html-разметка будет выглядеть следующим образом:

<a class="link" href="/Home/GetUser/12?name=Sam" id="sam">Sam</a>

Обратите внимание на знак @ перед словом class: поскольку слово "class" является зарезервированным словом в C#, то для правильного рендеринга нам надо перед ним указать знак @.

Html.RouteLink

Хелпер RouteLink использует похожий шаблон, что и ActionLink: он принимает имя маршрута, но не требует аргументов для имени контроллера и имени действия. Так, последний пример с ActionLink эквивалентен следующему коду:

@Html.RouteLink("Sam", new { controller = "Home", action = "GetUser", name = "Sam", id = 12 }, new { id = "sam", @class = "link" })

Чтобы использовать маршрут, нам просто надо указать имя определенного нами маршрута и затем определить при необходимости дополнительные параметры. Например, возьмем стандартный маршрут default, который определен в классе Startup:

app.UseEndpoints(endpoints =>
{
	endpoints.MapControllerRoute(
		name: "default",
		pattern: "{controller=Home}/{action=Index}/{id?}");
});

Тогда создать ссылку мы можем, например, так:

@Html.RouteLink("Все пользователи","Default",new { action = "UsersList" })

В данном случае используется шаблон марщрута с именем default - то есть трехсегментный шаблон, где последний сегмент не обязателен. Мы указали действие UsersList, но не указали контроллер, поэтому будет использоваться контроллер по умолчанию (если он указан в определении маршрута) - HomeController. В итоге сгенерированная ссылка будет выглядеть так:

<a href="/Home/UsersList">Все пользователи</a>

Собственно имена маршрутов и используются в основном для создания ссылок.

Система маршрутизации и генерация ссылок

При генерации ссылок фрейворк MVC опирается на систему маршрутизации. Допустим, в классе Startup определено несколько маршрутов:

app.UseEndpoints(endpoints =>
{
	endpoints.MapControllerRoute(
		name: "products",
		pattern: "Products/{action}/{id?}",
		defaults: new { controller = "Home" });

	endpoints.MapControllerRoute(
		name: "default",
		pattern: "{controller=Home}/{action=Index}/{id?}");
});

Первым здесь установлен маршрут "products", который будет сопоставлять запросы к контроллеру Home с маршрутом "Products/{action}/{id?}". В частности, запрос http://localhost:55994/Products/Index будет обрабатываться методом Index контроллера Home.

И теперь выражение

@Html.ActionLink("Жми здесь", "Index", "Home")

Сгенерирует следующую ссылку

<a href="/Products/Index">Жми здесь</a>

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

Так, пусть у нас определены следующие маршруты:

app.UseEndpoints(endpoints =>
{
	endpoints.MapControllerRoute(
		name: "default",
		pattern: "BookStore",
		defaults: new { controller = "Book", action = "Index" });
	endpoints.MapControllerRoute(
		name: "default1",
		pattern: "Store/Sub{action}/{id?}",
		defaults: new { controller = "Home" });

	endpoints.MapControllerRoute(
		name: "default2",
		pattern: "{controller=Home}/{action=Index}/{id?}");
});

Из определения маршрутов ясно, то запрос http://localhost:55994/BookStore будет обрабатываться методом Index контроллера Book. А запрос http://localhost:55994/Store/SubIndex/ будет обрабатываться контроллером Home и его методом Index.

Теперь пусть у нас в представлении создаются две ссылки:

@Html.ActionLink("Home", "Index", "Home")
@Html.ActionLink("Book", "Index", "Book")

Первая ссылка соответствует второму маршруту, так как для определения ссылки используется контроллер Home. Поэтому в соответствии со вторым маршрутом будет сгенерирована следующая ссылка:

http://localhost:55994/Store/SubIndex

Вторая же ссылка соответствует первому маршруту, который для обработки запроса применяет контроллер BookController. Поэтому второе выражение сгенерирует следующую ссылку:

http://localhost:55994/BookStore

Поэтому если в приложении определено несколько маршрутов, а в представлениях для генерации ссылок применяются хелперы типа Html.ActionLink, то следует проверять сгенерированные ссылки, иначе в результате можно получить совсем не то, что ожидалось.

Данные правила в отношении создания ссылок справедливы не только в отношении Html.ActionLink, но и в отношении хелпера Html.RouteUrl.

Например, вызов

@Html.RouteLink("Все книги", new { action = "Index", controller="Home" })

сгенерирует следующую ссылку:

<a href="/Store/SubIndex">Все книги</a>

Все, что было выше сказано в отношении маршрутов, применяется также в отношении атрибутов маршрутизации. Так, допустим, в контроллере HomeController используется атрибут Route:

public class HomeController : Controller
{
    [Route("api/[controller]/[action]")]
    public IActionResult Index()
    {
        return View();
    }
	
	// остальные методы
}

В этом случае вызов

@Html.ActionLink("Home", "Index", "Home")

сгенерирует следующую ссылку:

http://localhost:55994/api/Home/Index
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850