В прошлый раз мы познакомились с маршрутизацией в .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.