Бекенд на C# Web Api

To Kaiten

Фильтры

Action Filters в C# (и в ASP.NET Core) — это атрибуты, которые позволяют выполнять код до и после выполнения действий контроллера. Они используются для внедрения кросс-срезовой логики, такой как логирование, валидация, аутентификация, обработка исключений и другое.

Всего существует 5 типов фильтров:

  1. Фильтры авторизации (Authorization Filter)

  2. Фильтры ресурсов (Resource Filter)

  3. Фильтры действий (Action Filter)

  4. Фильтры результатов (Result Filter)

  5. Фильтры исключений (Exception Filter)

Action Filter

Рассмотрим более подробно фильтры на примере Action Filter.

  • Сперва необходимо создать класс и реализовать интерфейс IActionFilter. В методах OnActionExecuting и OnActionExecuted можно добавить любую логику, которая должна выполняться до или после выполнения action'а.

public class LogActionFilter : IActionFilter
{
    private readonly ILogger<LogActionFilter> _logger;

    // тут тоже работает внедрение зависимостей
    public LogActionFilter(ILogger<LogActionFilter> logger)
    {
        _logger = logger;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        //  Этот метод выполняется до метода контроллера
        _logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' is starting.");
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Этот метод выполняется после метода контроллера
        _logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' has completed.");
    }
}
  • Затем необходимо зарегистрировать фильтр в классе Program.

    • Глобальная регистрация — с помощью метода services.AddControllers регистрируются глобальные фильтры. Они действуют на все action'ы без исключения.

    • Выборочная регистрация — можно зарегистрировать фильтр используя методы AddSingleton, AddScoped или AddTransient. Такие фильтры должны применяться вручную к action'ам.

// регистрируем глобально
services.AddControllers(options =>
{
    options.Filters.Add<LogActionFilter>();
});

// или регистрируем для каждого запроса
services.AddScoped<LogActionFilter>();
  • Для использования фильтра нужно добавить атрибут ServiceFilter с указанием типа фильтра. Если фильтр зарегистрирован глобально, то добавлять этот атрибут не нужно.

[ServiceFilter(typeof(LogActionFilter))]
[HttpPost("registration")]
public async Task<IActionResult> Login()
{ ... }

Передача параметров в Action Filter

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

  • Создаем класс фильтра и указываем в конструкторе параметры, которые хотим передать. В примере ниже параметры limit и template должны передаваться вручную, а параметр logger внедряется автоматически с помощью DI.

public class RateLimitActionFilter : IActionFilter
{
    private readonly int _limit;
    private readonly string _template;
    private readonly ILogger<LogActionFilter> _logger;

    public RateLimitActionFilter(int limit, string template, ILogger<LogActionFilter> logger = null)
    {
        _limit = limit;
        _template = template;
        _logger = logger;
    }

    public void OnActionExecuting(ActionExecutingContext context) { ... }
    public void OnActionExecuted(ActionExecutedContext context) { ... }
}
  • Затем создаем класс кастомного атрибута. В конструкторе передаем в базовый класс тип исходного фильтра и задаем аргументы как список object'ов.

public class RateLimitAttribute : TypeFilterAttribute
{
    public RateLimitAttribute(int limit, string template) : base(typeof(RateLimitActionFilter))
    {
        Arguments = new object[] { limit, template };
    }
}
  • Используем атрибут с параметрами

[RateLimit(10, "template")]
[HttpPost("{phone}")]
public async Task<IActionResult> Register() { ... }

Ссылки

Хабр — Фильтры действий в ASP.NET Core


Автор документа: Артём Ветик