use. NET 6 developing TodoList application (12) -- implementing ActionFilter

Posted by defeated on Sun, 02 Jan 2022 11:51:50 +0100

Series navigation and source code

demand

Filter is in NET Web API project development is also a very important concept. It runs in the Pipeline executing MVC response, allowing us to extract some logic that can be reused among multiple actions for centralized management. Although we were in the last article use. NET 6 to develop TodoList application (11) -- using fluent validation and MediatR to implement interface request verification It demonstrates how to insert reusable code before and after the execution of the Handle method of CQRS by using the IPipelineBehavior interface provided by MediatR, and the Filters demonstrated in this article act before and after the execution of the Action of the Controller or the result returned by the Action.

You can create custom filters to handle cross slice concerns in your application. Cross slice concerns include error handling, caching, configuration, authorization, and logging. Filters can avoid duplicate code.

The types of filters are as follows:

  • Authorization Filters: run first to determine whether the user has been authorized for the request. If the request is not authorized, Authorization Filters can short circuit the pipeline.

  • Resource Filters: run after authorization. OnResourceExecuting runs the code before the rest of the Filter Pipeline. OnResourceExecuted runs the code after the rest of the pipeline is completed. You can use this type of Filter for caching and performance statistics.

  • Action Filters: run code immediately before and after the action method is called. It can change the parameters passed to the operation or the results returned from the operation. Of course, if nothing is changed, it can be recorded only.

  • Exception Filters: applies a global policy to unhandled exceptions before writing anything to the response body.

  • Result Filters: run the code before and after the result of the operation is returned. Action methods are run only if they execute successfully.

The five Filters are intuitively displayed in the Filter Pipeline as follows:

The stage of the entire FIlter Pipeline in the complete Middleware Pipeline is as follows:

In this article, we will demonstrate how Action Filters record request and response logs before and after the Action of the Controller is executed.

target

Use Action Filters for interface logging.

Principles and ideas

Create a custom Action Filter to implement the interface log logic of the Controller.

realization

Create a new folder Filters in Api and create a class LogFilterAttribute:

  • LogFilterAttribute.cs
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace TodoList.Api.Filters;

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

    public LogFilterAttribute(ILogger<LogFilterAttribute> logger) => _logger = logger;

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var action = context.RouteData.Values["action"];
        var controller = context.RouteData.Values["controller"];
        // Gets the parameter value whose name contains Command
        var param = context.ActionArguments.SingleOrDefault(x => x.Value.ToString().Contains("Command")).Value;

        _logger.LogInformation($"Controller:{controller}, action: {action}, Incoming request: {JsonSerializer.Serialize(param)}");
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        var action = context.RouteData.Values["action"];
        var controller = context.RouteData.Values["controller"];
        // You need to convert the Result to ObjectResult type before you can get the Value value
        var result = (ObjectResult)context.Result!;

        _logger.LogInformation($"Controller:{controller}, action: {action}, Executing response: {JsonSerializer.Serialize(result.Value)}");
    }
}

Dependency injection:

  • Program.cs
builder.Services.AddScoped<LogFilterAttribute>();

Add attributes on the Controller Action to which the Filter needs to be applied:

  • TodoListController.cs
[HttpPost]
[ServiceFilter(typeof(LogFilterAttribute))]
public async Task<ApiResponse<Domain.Entities.TodoList>> Create([FromBody] CreateTodoListCommand command)
{
    return ApiResponse<Domain.Entities.TodoList>.Success(await _mediator.Send(command));
}

verification

Start the Api project and execute the request to create TodoList:

  • request

  • response

    • Request data log from OnActionExecuting:

      Note the output before the Handling CreateTodoListCommand in our previous article.

    • And the return data log from OnActionExecuted output:

A little expansion

The topic about Filter also includes its scope, priority order and how to adjust the priority. Other topics such as how to rewrite the response, how to perform performance statistics and caching are not demonstrated here for the time being. Please refer to the official Microsoft documents: ASP. Filters in net core , learn more.

summary

In this article, we demonstrate the basic usage of Action Filter through a very simple example. So far, our discussion on request middleware pipeline has come to an end. Later, when we talk about authentication, we will come back to discuss this topic.

Starting from the next article, we will focus on some typical scenarios involved in query operation: paging, sorting, filtering, search, etc.

reference material

  1. ASP. Filters in net core

Topics: webapi