Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
При генерации ссылок фрейворк MVC опирается на систему маршрутизации. Допустим, в классе Startup определено несколько маршрутов:
using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace MvcRoutingApp { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); } public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); app.UseStaticFiles(); app.UseRouting(); 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")
Сгенерирует следующую ссылку
http://localhost:55994/Products/Index
И не смотря на то, что у нас также определен стандартный маршрут, который позволяет генерировать стандартные ссылки, включающие имя контроллера и имя его метода, но в данном случае для генерации ссылок будет применяться первый маршрут, который маршрут который совпадает с определением ссылки.
Так, пусть у нас определены следующие маршруты:
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "BookStore", defaults: new { controller = "Book", action="Index" }); routes.MapRoute( name: "default1", template: "Store/Sub{action}/{id?}", defaults: new { controller = "Home" }); routes.MapRoute( name: "default2", template: "{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, а также tag-хелпера AnchorTagHelper.
Например, вызов
@Html.RouteLink("Все книги", new { action = "Index", controller="Home" })
сгенерирует следующую ссылку:
<a href="/Store/SubIndex">Все книги</a>
А tag-хелпер
<a asp-action="Index" asp-controller="Book">Книги</a>
сгенерирует следующую ссылку:
<a href="/BookStore">Книги</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