Контроллеры

Контроллеры и их действия

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

Основным элементом в архитектуре ASP.NET Core MVC является контроллер. При получении запроса система маршрутизации выбирает для обработки запроса нужный контроллер и передает ему данные запроса. Контроллер обрабатывает эти данные и посылает обратно результат обработки.

Например, проект, создаваемый по шаблону ASP.NET Core Web App (Model-View-Controller), по умолчанию содержит как минимум один контроллер - класс HomeController со следующим кодом:

using HelloMvcApp.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;

namespace HelloMvcApp.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

В данном случае мы видим, что контроллер имеет конструктор, через который посредством механизма dependency injection передается сервис ILogger, используемый для логгирования. Также контроллер определяет три метода - Index, Privacy и Error.

Мы можем продолжить работу с этим контроллером, но в данном случае, чтобы упростить рассмотрение контроллеров и их функционала для работы возьмем простейший проект ASP.NET Core по типу ASP.NET Core Empty.

Подключение MVC в пустой проект ASP.NET Core

Пусть этот проект называется MvcApp. По умолчанию проект по данному шаблону не содержит никаких контроллеров. Поэтому нам надо их добавлять.

Добавление контроллера

При использовании контроллеров существуют некоторые условности. Прежде всего обычно в проекте контроллеры помещаются в каталог Controllers. Однако это в принципе необязательно - можно добавлять контроллеры в другие папки или даже в корень проекта. Тем не менее вначале добавим в проект новую папку Controllers.

В ASP.NET Core MVC контроллер представляет обычный класс на языке C#, который обычно наследуется от абстрактного базового класса Microsoft.AspNetCore.Mvc.Controller и который, как и любой класс на языке C#, может иметь поля, свойства, методы. Согласно соглашениям об именовании названия контроллеров обычно оканчиваются на суффикс "Controller", остальная же часть до этого суффикса считается именем контроллера, например, HomeController. Но в принципе эти условности также необязательны.

Но есть также и обязательные условности, которые предъявляются к контроллерам. В частности, класс контроллера должен удовлетворять как минимум одному из следующих условий:

  • Класс контроллера имеет суффикс "Controller"

    public class HomeController
    {  
    	//............  
    }
    
  • Класс контроллера наследуется от класса, который имеет суффикс "Controller"

    public class Home : Controller
    {
    	//.............
    }
    
  • К классу контроллера применяется атрибут [Controller]

    [Controller]
    public class Home
    {
    	//..................
    }
    

Теперь добавим в проект в папку Controllers новый класс, который назовем HomeController. Для добавления контроллера в проект можно использовать готовый шаблон MVC Controller - Empty:

Добавление контроллера в ASP.NET Core MVC в C#

То есть у нас получится следующий проект:

Контроллеры в ASP.NET Core MVC в C#

Действия контроллера

Ключевым элементом контроллера являются его действия. Действия контроллера - это публичные методы, которые могут сопоставляться с запросами. Например, возьмем контроллер HomeController и определим в нем метод Index:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public string Index()
        {
            return "Hello METANIT.COM";
        }
    }
}

В данном случае метод Index имеет модификатор public и поэтому может использоваться для обработки запроса. Данный метод возвращает строку. А это значит, что при обращении к этому действию приложение отправит в ответ пользователю данную строку.

Обращение к действиям контроллера

Сопоставление запроса с контроллером и его действием происходит благодаря системе маршрутизации. И для настройки сопоставления запросов с контроллерами перейдем к файлу Program.cs и изменим его следующим образом:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();	// добавляем поддержку контроллеров

var app = builder.Build();

// устанавливаем сопоставление маршрутов с контроллерами
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Прежде всего добавляем поддержку контроллеров MVC с помощью следующего вызова:

builder.Services.AddControllers();

Далее настраиваем сопоставление маршрутов с контроллерами:

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

Метод app.MapControllerRoute добавляет один маршрут с именем default и шаблоном "{controller=Home}/{action=Index}/{id?}". Данный шаблон устанавливает трехсегментную структуру строки запроса: controller/action/id. То есть в начале идет название контроллера, затем название действия, и далее может идти необязательный параметр id.

Собственно поэтому система может соотнести запрос типа localhost:xxxx/Home/Index с контроллером и его действием.

Чтобы обратиться контроллеру из веб-браузера, нам надо в адресной строке набрать адрес_сайта/Имя_контроллера/Действие_контроллера. Так, по запросу адрес_сайта/Home/Index система маршрутизации по умолчанию вызовет метод Index контроллера HomeController для обработки входящего запроса. Например:

Обращение к методу контроллера ASP.NET Core MVC в языке C#

Методы, которые не являются действиями

Однако не все методы контроллера являются действиями. Контроллер также может иметь непубличные методы - такие методы не рассматриваются как действия и соответственно не могут соотноситься с запросами. Например, определим в контроллере следующий метод:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        public string Index() => "Hello METANIT.COM";
        
        protected internal string Hello() => "Hello ASP.NET";
    }
}

Здесь метод Hello не является действием, поскольку его модификатор отличается от public. Соответственно мы не сможем обратиться к этому методу с запросом localhost:xxxx/Home/Hello. Хотя такие не публичные методы также могут быть полезными - в них можно определять какие-нибудь промежуточные вычисления и затем использовать в действиях контроллера. При этом если мы изменим модификатор метода на public, то метод Hello станет полноценным действием:

Атрибуты NonController, ActionName и NonAction

Возможно, сопоставление по умолчанию бывает не всегда удобно. Например, у нас есть класс в папке Controllers, но мы не хотим, чтобы он мог обрабатывать запрос и использоваться как контроллер. Чтобы указать, что этот класс не является контроллером, нам надо использовать над ним атрибут [NonController]:

[NonController]
public class HomeController : Controller
{
	//...........
}

Аналогично, если мы хотим, чтобы какой-либо публичный метод контроллера не рассматривался как действие, то мы можем использовать над ним атрибут NonAction:

[NonAction]
public string Hello()
{
    return "Hello ASP.NET";
}

Атрибут [ActionName] позволяет для метода задать другое имя действия. Например:

[ActionName("Welcome")]
public string Hello()
{
    return "Hello ASP.NET";
}

В этом случае чтобы обратиться к этому методу, надо отправить запрос localhost:xxxx/Home/Welcome. А запрос localhost:xxxx/Home/Hello работать не будет.

Типы запросов

Кроме того, методы могут обслуживать разные типы запросов. Для указания типа запроса HTTP нам надо применить к методу один из атрибутов: [HttpGet], [HttpPost], [HttpPut], [HttpPatch], [HttpDelete] и [HttpHead]. Если атрибут явным образом не указан, то метод может обрабатывать все типы запросов: GET, POST, PUT, DELETE.

Например:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public string Index() => "Hello METANIT.COM";

        [HttpPost]
        public string Hello() => "Hello ASP.NET";
    }
}

Так, в данном случае метод Index обрабатывает только запросы типа GET, а метод Hello - запросы типа POST.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850