Обработка запросов с помощью контроллеров в ASP.NET Core MVC

Авторы: Стив Смит (Steve Smith) и Скотт Эдди (Scott Addie)

Контроллеры, действия и результаты действий являются основополагающей составляющей разработки приложений с помощью ASP.NET Core MVC.

Что такое контроллер?

Контроллер используется для определения и группировки набора действий. Действие (или метод действия) — это метод на контроллере, обрабатывающий запросы. Контроллеры логически группируют схожие действия. Это объединение действий позволяет коллективно применять общие наборы правил, например маршрутизации, кэширования и авторизации. Запросы сопоставляются с действиями посредством маршрутизации. Контроллеры активируются и удаляются на основе каждого запроса.

По соглашению классы контроллеров:

  • размещаются в папке Controllers на корневом уровне проекта.
  • Наследуйте от Microsoft.AspNetCore.Mvc.Controller.

Контроллер является экземплярным классом, обычно общедоступным, в котором по крайней мере одно из следующих условий имеет значение true:

  • Имя класса имеет суффикс Controller.
  • Класс наследует от класса, имя которого имеет суффикс Controller.
  • К классу применяется атрибут [Controller].

С классом контроллера не должен быть связан атрибут [NonController].

Контроллеры должны соответствовать принципу явных зависимостей. Существует несколько подходов к реализации этого принципа. Если нескольким действиям контроллера требуется одна служба, рекомендуется использовать внедрение через конструктор для запроса этих зависимостей. Если служба требуется только одному методу действия, рекомендуется использовать внедрение действий для запроса зависимости.

В рамках шаблона MVC контроллер отвечает за начальную обработку запроса и создание экземпляра модели. Как правило, бизнес-решения следует выполнять внутри модели.

Контроллер принимает результат обработки модели (если он есть) и возвращает подходящее представление и связанные с ним данные или результат вызова API. Дополнительные сведения см. в разделах Общие сведения о ASP.NET Core MVC и Начало работы с ASP.NET Core MVC и Visual Studio.

Контроллер является абстракцией на уровне пользовательского интерфейса. Он должен проверить допустимость данных запроса и выбрать возвращаемое представление (или результат для API). В хорошо организованных приложениях он не включает в себя доступ к данным или бизнес-логику напрямую. Вместо этого контроллер делегирует обработку этих обязанностей службам.

Определение действий

Открытые методы в контроллере, кроме имеющих атрибут [NonAction], являются действиями. Параметры для действий привязаны к данным запроса и проверяются с помощью привязки модели. Проверка модели выполняется для всего, что привязано к модели. Значение свойства ModelState.IsValid указывает успешность привязки и проверки модели.

Методы действия должны содержать логику для сопоставления запроса с бизнес-фактором. В общем случае бизнес-факторы должны быть представлены в виде служб, к которым контроллер обращается посредством внедрения зависимостей. После этого действия сопоставляют результат бизнес-операции с состоянием приложения.

Действия могут возвращать любое значение, но часто возвращают экземпляр IActionResult (или Task<IActionResult> для асинхронных методов), формирующий отклик. Метод действия отвечает за выбор типа отклика. Результат действия осуществляет отклик.

Вспомогательные методы Controller

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

1. Методы, приводящие к пустому тексту ответа

Заголовок HTTP-отклика Content-Type не включается, так как в тексте отклика нет содержимого для описания.

В этой категории есть два типа результатов: перенаправление и код состояния HTTP.

  • Код состояния HTTP

    Этот тип возвращает код состояния HTTP. К этому типу вспомогательных методов относятся BadRequest, NotFound и Ok. Например, при выполнении return BadRequest(); создает код состояния 400. Если такие методы, как BadRequest, NotFound и Ok, перегружены, они больше не могут выступать в качестве ответчиков кода состояния HTTP, так как выполняется согласование содержимого.

  • Перенаправление

    Этот тип возвращает перенаправление в действие или назначение (с помощью Redirect, LocalRedirect, RedirectToAction или RedirectToRoute). Например, return RedirectToAction("Complete", new {id = 123}); перенаправляет Complete, передав анонимный объект.

    Тип результатов перенаправления отличается от кода состояния HTTP, главным образом, добавлением заголовка HTTP-отклика Location.

2. Методы, приводящие к непустой теле отклика с предопределенным типом контента

Большинство вспомогательных методов в этой категории имеют свойство ContentType, что позволяет задать заголовок отклика Content-Type для описания основного текста отклика.

В этой категории есть два типа результатов: представление и форматированный отклик.

  • Представление

    Этот тип возвращает представление, использующее модель для отрисовки HTML. Например, return View(customer); передает модель в представление для привязки данных.

  • Форматированный отклик

    Этот тип возвращает JSon или аналогичный формат обмена данными для представления объекта определенным образом. Например, return Json(customer); сериализует предоставленный объект в JSформате ON.

    Другими распространенными методами этого типа являются File и PhysicalFile. Например, return PhysicalFile(customerFilePath, "text/xml"); возвращает PhysicalFileResult.

3. Методы, в результате чего текст ответа, форматированный в типе контента, согласованный с клиентом

Эта категория более известна как согласование содержимого. Согласование содержимого применяется всякий ObjectResult раз, когда действие возвращает тип или что-то другое, отличное IActionResult от реализации. Действие, которое возвращает значение, отличное от реализации IActionResult (например, object), также возвращает форматированный отклик.

Другими вспомогательными методами этого типа являются BadRequest, CreatedAtRoute и Ok. Примерами этих методов являются return BadRequest(modelState);, return CreatedAtRoute("routename", values, newobject); и return Ok(value);, соответственно. Обратите внимание, что BadRequest и Ok выполняют согласование содержимого только при передаче значения. Без передачи значения они выступают в качестве типов результатов для кода состояния HTTP. С другой стороны, метод CreatedAtRoute всегда выполняет согласование содержимого, так как все его перегрузки требуют передачи значения.

Сквозная функциональность

Приложения обычно имеют общие части рабочего процесса. В качестве примера можно привести приложение, которое требует пройти проверку подлинности для доступа к корзине для покупок, или приложение, кэширующее данные на некоторых страницах. Чтобы выполнить логику до или после метода действия, используйте фильтр. Использование фильтров наряду со сквозной функциональностью позволяет уменьшить дублирование.

Большинство атрибутов фильтров, например [Authorize], можно применить на уровне контроллера или действия в зависимости от нужного уровня детализации.

Обработка ошибок и кэширование откликов часто относятся к сквозной функциональности:

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