В прошлый раз мы познакомились с маршрутизацией в .NET 2.2. Маршрутизация в .NET Core MVCи тогда мы говорили о том, как все работает из коробки. Сегодня мы будем говорить о том, как можно с помощью атрибутов более гибко настраивать URL к определенному коду.
Давайте создадим новый контроллер. Откройте проект из Кликаем правой кнопкой по папке Controllers и выбираем создание нового файла. В появившемся окне MVC Controller Class или можно даже любой другой тип .cs файла, ведь главное это расширение и имя, а имя для нашего теста будет TestController.
Начнем с простого варианта:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace MyWebSite { public class TestController : Controller { public string Index() { return "Test Index method"; } } }
Пока ничего нового – просто класс TestController, который происходит от базового контроллера Controller. Здесь метод по умолчанию Index. С маршрутизацией по умолчанию, которую мы рассматривали в предыдущей части, обращение к этому методу через браузер может быть через URL: /test/index. А что, если мы хотим сделать так, чтобы URL выглядел как /my/test/index?
Проблему можно решить двумя способами – первый (старый) добавить еще один маршрут. Открываем файл Startup.cs, находим вызов метода UseMvc в Configure и добавляем туда еще один маршрут:
app.UseMvc(routes => { routes.MapRoute( name: "my", template: "my/{controller=Home}/{action=Index}/{id?}" ); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}" ); });
Теперь я дважды вызываю MapRoute. Первый параметр Name должен быть уникальным и просто отображать маршрут. Сначала желательно вызывать как можно более ограниченный маршрут, а потом уже более общий. По умолчанию относится как раз к общим. Наш новый более ограниченный, потому что должен работать только тогда, когда URL начинается с my/.
Запускаем приложение и можно убедиться, что все работает и теперь при обращении к /home/index и /my/test/index мы можем увидеть два уникальных страницы. Но это старый, не очень удобный подход, который я предпочитаю не использовать. Более удобный вариант – атрибуты. Перед именем класса и метода можно написать атрибут Route и в нем перезаписать часть URL.
В следующем примере я показал, пару интересных примеров, как можно через атрибуты указать маршрут:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace MyWebSite { [Route("my/test")] public class TestController : Controller { [Route("show")] public string Index() { return "Index Test method"; } [Route("details/{id}")] public string Details(string id) { return "ID Value = " + id; } } }
Перед строкой объявления класса я указываю, что все методы класса будут вызываться только тогда, когда URL начинается с my/test. В случае с классом в аттрибуте можно использовать Route или раньше еще поддерживался RoutePrefix, который похоже уже выпилили.
... namespace MyWebSite { [Route("my/test")] public class TestController : Controller { [Route("show")] public string Index() { return "Index Test method"; } ... ... } }
Теперь перед методами нужно указать оставшуюся часть URL. Для метода Index я указал show, а значит если загрузить URL /my/test/show, то будет вызван метод Index класса TestController.
Для метода Details указано details/{id}. Здесь фигурные скобки вокруг id не случайны. Этим мы указываем, что значение в этом месте будет передано самому методу в качестве параметра id.
Итак, если обратиться по адресу: /my/test/details/4, то будет вызван метод Details класса TestController, а число 4 как раз находится там, где у нас шаблон {id}, а значит это число передадут в качестве параметра id.