Роутинг на основе атрибутов в приложении ASP.NET Core MVC

Прежде чем разбираться с маршрутизацией атрибутов в приложении ASP.NET Core MVC, давайте сначала внесем некоторые изменения в наше приложение. Сначала измените метод Configure() файла Startup.cs, как показано ниже. Мы используем метод UseMvc() без передачи шаблона маршрута по умолчанию в качестве параметра.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc();
    }
}

С учетом вышеуказанных изменений в методе Configure теперь у нашего приложения нет настроенных маршрутов для обработки запроса и ответа.

Теперь отредактируем HomeController, как показано ниже.

public class HomeController : Controller
{
    public string Index()
    {
        return "Index() Action Method of HomeController";
    }
}

Теперь, когда вы перейдете по любому из приведенных ниже URL-адресов, вы получите 404 ошибки. Это связано с тем, что в настоящее время в нашем приложении нет настроенного маршрута для обработки запроса.

http://localhost:5000
http://localhost:5000/home
http://localhost:5000/home/index

Давайте посмотрим, как использовать роутинг на основе атрибутов для сопоставления входящих URL-адресов с методом действия Index контроллера HomeController.

Маршрутизация атрибутов в ASP.NET Core MVC:

С помощью ASP.NET Core Attribute Routing вы можете использовать атрибут Route для определения маршрутов для вашего приложения. Вы можете использовать атрибут Route либо на уровне контроллера, либо на уровне методов действия контроллера. Когда вы применяете атрибут Route на уровне контроллера, он применим ко всем методам действий этого контроллера.

Давайте отредактируем HomeController, как показано ниже. Здесь мы применили атрибут Route к методу Action.

using Microsoft.AspNetCore.Mvc;
namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        [Route("")]
        [Route("Home")]
        [Route("Home/Index")]
        public string Index()
        {
            return "Index() Action Method of HomeController";
        }
    }   
}

Если вы заметили, здесь мы применили атрибут Route() три раза к методу действия Index() контроллера HomeController. Необходимо помнить, что для каждого экземпляра атрибута Route мы указывали свой шаблон маршрута. С указанными выше тремя атрибутами Route теперь мы можем получить доступ к методу действия Index() контроллера HomeController, используя URL-адреса, указанные ниже.

http://localhost:5000
http://localhost:5000/home
http://localhost:5000/home/index

Теперь запустите приложение и перейдите по вышеуказанным URL-адресам, и вы увидите ожидаемый результат.

Маршрутизация атрибутов с параметрами в приложении ASP.NET Core MVC:

С помощью маршрутизации на основе соглашений (Conventional-Based routing) мы можем указать параметры маршрута как часть шаблона маршрута. Мы также можем сделать то же самое с маршрутизации на основе атрибутов (Attribute-Based routing). Это означает, что мы также можем определить атрибут маршрута с параметрами. Чтобы проверить это, измените HomeController, как показано ниже.

using Microsoft.AspNetCore.Mvc;

namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        [Route("")]
        [Route("Home")]
        [Route("Home/Index")]
        public string Index()
        {
            return "Index() Action Method of HomeController";
        }
        [Route("Home/Details/{id}")]
        public string Details(int id)
        {
            return "Details() Action Method of HomeController, ID Value = " + id;
        }
    }   
}

Как видно из приведенного выше кода, метод действия Details() имеет параметр id. Обратите внимание, что в шаблоне маршрута мы также указали параметр i. Таким образом, URL /Home/Details/10 выполнит метод действия Details(int id) и передаст значение 10 в параметр id метода действия Details. Это делается с помощью процесса связывания моделей. Теперь запустите приложение и перейдите по указанному ниже URL-адресу, и вы увидите ожидаемый результат.

http://localhost:52190/Home/Details/10

Маршрутизация атрибутов с необязательными параметрами в приложении ASP.NET Core MVC:

Как и в случае с маршрутизации на основе соглашений, мы также можем сделать параметр необязательным в маршрутизации на основе атрибутов. Чтобы сделать параметр Route необязательным, просто добавьте знак вопроса ? В конце параметра.

using Microsoft.AspNetCore.Mvc;

namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        [Route("")]
        [Route("Home")]
        [Route("Home/Index")]
        public string Index()
        {
            return "Index() Action Method of HomeController";
        }
        [Route("Home/Details/{id?}")]
        public string Details(int id)
        {
            return "Details() Action Method of HomeController, ID Value = " + id;
        }
    }   
}
Теперь запустите приложение и перейдите по указанному ниже URL, и вы увидите ожидаемый результат, вместо ошибки 404.

http://localhost:52190/Home/Details/

Именование контроллеров и методов действий в маршрутизации атрибутов:

При использовании маршрутизации на основе атрибутов в приложении ASP.NET Core MVC имена контроллеров и методов действий не играют большой роли. Чтобы понять это, измените HomeController, как показано ниже.

using Microsoft.AspNetCore.Mvc;s
namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        [Route("")]
        [Route("MyHome")]
        [Route("MyHome/Index")]
        public string StartPage()
        {
            return "StartPage() Action Method of HomeController";
        }
    }   
}

Как видите, мы трижды указали атрибут Route у метода действия StartPage() контроллера HomeController. Таким образом, метод действия StartPage() будет выполняться для следующих 3-х URL-адресов.

/
/MyHome
/MyHome/Index

Роутинг на основе атрибутов на уровне контроллера:

В приложении ASP.NET Core MVC также возможно применить атрибут Route() к классу Controller, а также к отдельным методам действий. Если вы хотите сделать атрибут маршрутизации менее повторяющимся, то вам нужно использовать атрибуты маршрута на уровне контроллера, а также на уровне отдельных методов действий. Чтобы в этом убедиться отредактируем класс HomeController, как показано ниже.

using Microsoft.AspNetCore.Mvc;
namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        [Route("")]
        [Route("Home")]
        [Route("Home/Index")]
        public string Index()
        {
            return "Index() Action Method of HomeController";
        }
        [Route("Home/Details/{id?}")]
        public string Details(int id)
        {
            return "Details() Action Method of HomeController, ID Value = " + id;
        }
    }
}

С помощью приведенного выше кода мы можем получить доступ к методу действия Index(), используя следующие 3 URL-адреса.

/
/Home
/Home/Index

В той же строке мы также можем получить доступ к методу действия Details(int? Id), используя следующие 2 URL.

/Home/Details
/Home/Details/2

Если вы заметили, мы используем слово Home несколько раз (в нашем примере четыре раза). Чтобы не дублировать эти маршруты, нам нужно применить атрибут Route() со словом Home на уровне класса HomeController, как показано ниже.

using Microsoft.AspNetCore.Mvc;
namespace FirstCoreMVCApplication.Controllers
{
    [Route("Home")]
    public class HomeController : Controller
    {
        [Route("")]       
        [Route("Index")]
        public string Index()
        {
            return "Index() Action Method of HomeController";
        }
        [Route("Details/{id?}")]
        public string Details(int id)
        {
            return "Details() Action Method of HomeController, ID Value = " + id;
        }
    }
}

Примечание. Шаблон маршрута, применяемый на уровне контроллера, добавляется к шаблону маршрута, применяемому к уровню метода действия.

Теперь, при переходе по следующим четырем URL-адресам, вы получите ожидаемый результат.

/Home
/Home/Index
/Home/Details
/Home/Details/2

Однако при переходе к корневому URL-адресу http://localhost:5000 приложения вы получите ошибку 404. Чтобы решить эту проблему, необходимо включить шаблон маршрута, который начинается с /, в метод действия Index(), как показано ниже.

[Route("")]
[Route("/")]
[Route("Index")]
public string Index()
{
    return "Index() Action Method of HomeController";
}

После внесения вышеуказанных изменений запустите приложение и перейдите по корневому URL-адресу, чтобы увидеть ожидаемый результат.

Как игнорировать шаблон маршрута, размещенный на уровне контроллера?

Чтобы игнорировать шаблон маршрута, размещенный на уровне контроллера, необходимо использовать / или ~/ на уровне метода действия.

Если шаблон маршрута метода действия начинается с / или ~/ тогда шаблон маршрута контроллера не будет объединен с шаблоном маршрута метода действия.

Чтобы проверить это, изменим класс HomeController, как показано ниже. В следующем коде метод действия About начинается с ~/ поэтому этот метод действия не будет сочетаться с шаблоном маршрута контроллера.

[Route("Home")]
public class HomeController : Controller
{
    [Route("~/About")]
    public string About()
    {
        return "About() Action Method of HomeController";
    }
}

Теперь запустите приложение и перейдите по ссылке /About, и вы увидите ожидаемый результат.