ASP.NET Core MVC Filter from entry to mastery

With the development of technology, ASP.NET Core MVC has also been launched for a long time. After continuous version update iterations, it has become more and more perfect. This series of articles mainly explains the related content involved in the process of ASP.NET Core MVC development B/S system. It is suitable for beginners, school graduates, or other personnel who want to engage in ASP.NET Core MVC system development.

After the explanations of the previous articles, I have a preliminary understanding of ASP.NET Core MVC project creation, startup and operation, and naming conventions, creating controllers, views, models, receiving parameters, passing data ViewData, ViewBag, routing, page layout, wwwroot and client libraries, Razor syntax, EnityFrameworkCore and databases, HttpContext, Request, Response, Session, serialization, file upload, automatic mapping, Html auxiliary tags, model verification, authentication, authorization basics, Identity entry, logs Management and other content, today continue to explain the Filter (filter) and other related content in ASP.NET Core MVC, which is only for learning and sharing .

What is Filter?

Filter is also known as filter, filter. In an ASP.NET Core MVC project, by using a Filter, you can run code before or after a specific point in the request processing pipeline. You can create a custom Filter to handle cross-cutting concerns, similar to AOP aspect-oriented programming. For creating Filter, code duplication can be reduced, for example, error handling exception filter can incorporate error handling.

Filter working principle

From the beginning of the request to the end of the request, through a series of nodes, the call pipeline is formed. Filter runs in the call pipeline of ASP.NET Core MVC, and the filter is equivalent to several hooks set in the pipeline to execute specific code.

Filter type

According to different processing functions, filters are mainly divided into the following categories:

  • Authorization filter AuthorizationFilter:

    • Run first.
    • Determine if the user is authorized for the request.
    • Pipelines can be short-circuited if the request is not authorized.
  • Resource Filter Resource Filter:

    • run after authorization.
    • OnResourceExecuting runs code before the rest of the filter pipeline. For example, OnResourceExecuting run code before model binding.
    • OnResourceExecuted runs code after the rest of the pipeline has completed.
  • Action Filter Action Filter:

    • Runs immediately before and after the action method is called.
    • The parameters passed into the action can be changed.
    • The result returned from an operation can be changed.
    • Not available in Razor Pages.
  • Exception Filter: Applies a global policy to unhandled exceptions before writing anything to the response body.

  • Result Filter Result Filter:

    • Runs immediately before and after the result of an action.
    • Will only run if the action method executes successfully.
    • Can be useful for logic that must wrap around the execution of views or formatters.

 The following diagram shows how Filter types interact in a filter pipeline:

Filter implementation

All filters implement the interface IFilterMetadata. According to different business types, five interfaces are derived, corresponding to five types of filters, as follows:

Note: The above five interfaces also have a corresponding asynchronous interface (Async).

Filter scope

Filter can act on Controller, Action, and global. The following example illustrates the order in which filter methods are run for a synchronous operation filter:

Authorization Filter

Authorization filter:

  • is the first filter run in the filter pipeline.
  • Control access to action methods.
  • Has methods that execute before it, but not methods that execute after it.

For example, the commonly used RequireHttps is an authorization filter, which implements the IAuthorizationFilter interface and inherits Attirbute, so it can be used in Controller or Action. in a way that restricts requests.

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

namespace Microsoft.AspNetCore.Mvc
{
    //
    // 摘要:
    //     An authorization filter that confirms requests are received over HTTPS.
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class RequireHttpsAttribute : Attribute, IAuthorizationFilter, IFilterMetadata, IOrderedFilter
    {
        public RequireHttpsAttribute();

        public int Order { get; set; }

        public virtual void OnAuthorization(AuthorizationFilterContext filterContext);

        protected virtual void HandleNonHttpsRequest(AuthorizationFilterContext filterContext);
    }
}

Resource Filter

The resource filter is executed after the authorization filter, and needs to implement the IResourceFilter interface. As follows:

using Microsoft.AspNetCore.Mvc.Filters;

namespace DemoCoreMVC.Filter
{
    /// <summary>
    /// 同步版本
    /// </summary>
    public class LogResourceFilter :Attribute, IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            //Action执行完成后执行
            Console.WriteLine("********************On Resource Filter Executed********************");
        }

        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            //授权Filter执行后执行。
            Console.WriteLine("********************On Resource Filter Executing********************");
        }
    }

    /// <summary>
    /// 异步版本
    /// </summary>
    public class AsynLogResouceFilter : Attribute, IAsyncResourceFilter
    {
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            Console.WriteLine("********************On Aysnc Resource Filter Executing********************");
            var exceutedContext =  await next();
            Console.WriteLine("********************On Async Resource Filter Executed********************");
        }
    }
}

Resource filters are useful if you want to short-circuit most of your pipeline. For example, if there is a cache hit, the cache filter can bypass the rest of the pipeline.

Operation Filter

Action filters are not applied to Razor Pages. Razor Pages supports IPageFilter and IAsyncPageFilter.

Action filter:

  • Implement the IActionFilter or IAsyncActionFilter interface.
  • Their execution revolves around the execution of action methods.

The following code shows a sample action filter:

using Microsoft.AspNetCore.Mvc.Filters;

namespace DemoCoreMVC.Filter
{
    public class DoDoActionFilter : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {

            Console.WriteLine("********************On Action Executed********************");
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            Console.WriteLine("********************On Action Executing********************");
        }
    }

    public class AsyncDoDoActionFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {

            Console.WriteLine("********************On Async Action Executing********************");
            await next();
            Console.WriteLine("********************On Async Action Executed********************");
        }
    }
}

ActionExecutingContext provides the following properties:

  • ActionArguments - Used to read the input of the action method.
  • Controller - Used to handle controller instances.
  • Result - Setting  Result short-circuits execution of action methods and subsequent action filters.

ActionExecutedContext provides  Controller and  Result and the following properties:

  • Canceled - true if the action execution has been short-circuited by another filter setting.
  • Exception - non-NULL if the action or a previously run action filter threw an exception. Set this property to null:
    • Handle exceptions efficiently.
    • Execute  Result, return it from the action method.

For  IAsyncActionFilter, a call to ActionExecutionDelegate can achieve the following:

  • Executes all subsequent action filters and action methods.
  • return  ActionExecutedContext.

Abnormal Filter

Exception filter:

  • Implement IExceptionFilter or IAsyncExceptionFilter.
  • Can be used to implement common error handling strategies.

The following exception filter example shows details about exceptions that occur while developing an application:

using Microsoft.AspNetCore.Mvc.Filters;

namespace DemoCoreMVC.Filter
{
    public class DoExceptionFilter :Attribute, IExceptionFilter
    {
        public void OnException(ExceptionContext context)
        {
            Console.WriteLine("********************On Exception********************");
        }
    }

    public class DoAsyncExceptionFilter : Attribute, IAsyncExceptionFilter
    {
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("********************On Exception Async********************");
            });

        }
    }
}

Exception filter:

  • There are no before and after events.
  • Implement OnException or OnExceptionAsync.
  • Handles unhandled exceptions that occur in Razor Page or controller creation, model binding, action filters, or action methods.
  • Please do not catch exceptions that occur in resource filters, result filters, or MVC result execution.

To handle exceptions, set the ExceptionHandled property to  true or assign the Result property. This will stop the exception from propagating. Exception filters cannot turn exceptions into "success". Only action filters can perform this transformation.

Exception filter:

  • Great for catching exceptions that occur during operations.
  • Not as flexible as error handling middleware.

It is recommended to use middleware to handle exceptions. Exception filters are used only if the error handling differs based on the action method being called. For example, an app might have action methods for API endpoints and views/HTML. API endpoints can return error information as JSON, while view-based operations may return error pages as HTML.

Results Filter

Result filter:

  • Implement the interface:
    • IResultFilter 或 IAsyncResultFilter
    • IAlwaysRunResultFilter or IAsyncAlwaysRunResultFilter
  • Their execution revolves around the execution of the result of the operation.
using Microsoft.AspNetCore.Mvc.Filters;

namespace DemoCoreMVC.Filter
{
    public class DoResultFilter :Attribute, IResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            Console.WriteLine("********************On Result Executed********************");
        }

        public void OnResultExecuting(ResultExecutingContext context)
        {
            Console.WriteLine("********************On Result Executing********************");
        }
    }

    public class DoAysncResultFilter :Attribute, IAsyncResultFilter
    {
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {
            Console.WriteLine("********************On Result Execution Async Executing********************");
            await next();
            Console.WriteLine("********************On Result Execution Async Executed********************");
        }
    }

}

Filter test

Put the written filter on Home/Index, as shown below:

[DoExceptionFilter]
[LogResourceFilter]
[DoResultFilter]
[DoDoActionFilter]
public IActionResult Index()
{
    _logger.LogInformation("Hello, 这是首页!");
    return View();
}

The test looks like this:

Explanation: The exception filter has no output content because no exception is generated. Authorization filters are not added, start before all filters and end after all filters.

Filter global application

Filter can be applied to a single Controller or Action, or it can be applied globally. The code is as follows:

builder.Services.AddControllersWithViews(option =>
{
    option.Filters.Add<LogResourceFilter>();
    option.Filters.Add<DoExceptionFilter>();
    option.Filters.Add<DoResultFilter>();
    option.Filters.Add<DoDoActionFilter>();
});

A global test looks like this:

The above is the whole content of Filter of ASP.NET Core MVC from entry to mastery.

reference documents

Official document: https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0

Guess you like

Origin blog.csdn.net/fengershishe/article/details/131333274