Переопределение контроллеров

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

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

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

Что мы можем в контроллере переопределить? В базовом классе Controller среди всех прочих методов есть три интересных метода:

[NonAction]
public virtual void OnActionExecuting(ActionExecutingContext context)
{
}
[NonAction]
public virtual void OnActionExecuted(ActionExecutedContext context)
{
}
[NonAction]
public virtual async Task OnActionExecutionAsync(ActionExecutingContext context,
            ActionExecutionDelegate next)
{
    if (context == null)
    {
        throw new ArgumentNullException(nameof(context));
    }

    if (next == null)
    {
        throw new ArgumentNullException(nameof(next));
    }

    OnActionExecuting(context);
    if (context.Result == null)
    {
        OnActionExecuted(await next());
    }
}

Метод OnActionExecuting() выполняется при вызове метода контроллера до его непосредственного выполнения.

Метод OnActionExecuted() выполняется после выполнения метода контроллера.

Метод OnActionExecutionAsync() представляет асинхронную версию метода OnActionExecuting().

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

Для решения этой задачи добавим в папку Controllers следующий класс контроллера:

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public abstract class HelloBaseController : Controller
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.HttpContext.Request.Headers.ContainsKey("User-Agent"))
		{
			// получаем заголовок User-Agent
			var useragent = context.HttpContext.Request.Headers["User-Agent"].FirstOrDefault();
			// сравниваем его значение
			if(useragent.Contains("MSIE") || useragent.Contains("Trident"))
			{
				context.Result = Content("Internet Explorer не поддерживается");
			}
		}
        base.OnActionExecuting(context);
    }
}

Так как нам надо переопределить поток выполнения программы до начала выполнения действия, то переопределяется метод OnActionExecuting(). В качестве параметра он принимает контекст выполнения метода - объект ActionExecutingContext, из которого мы можем получить самую различную информацию, в том числе и обратиться к контексту запроса.

Первым делом проверяем, установлен ли заголовок "User-Agent":

context.HttpContext.Request.Headers.ContainsKey("User-Agent")

Если установлен, то содержит ли этот User-Agent подстроки "MSIE" или "Trident":

if(useragent.Contains("MSIE") || useragent.Contains("Trident"))

И далее переопределяется результат метода в виде переадресации:

context.Result = Content("Internet Explorer не поддерживается");

Также мы бы могли переопределить какие-либо другие действия или определить новые общие для всех действия.

И теперь мы можем унаследовать контроллеры от нашего базового класса:

public class HomeController : HelloBaseController
{
    public IActionResult Index()
    {
        return Content("Запрос успешно выполнен");
    }
	// остальные методы контроллера
}

И теперь до начала работы метода Index будет срабатывать метод OnActionExecuting(), определенный в базовом классе HelloBaseController.

Overriding controllers in ASP.NET Core MVC
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850