asp.net core web api model naming rule coding style appsettings visual studio code restful api

ASP.NET Core 5 EP 14:Filter-封包篩選條件管線化

什麼是Filter

Filter是於Action前/後所被定義用作處理封包的功能,其定義有5種Filter,包括Authorization Filter、Resource Filter、Action Filter、Exception Filter 及 Result Filter,其功能分別如下:

  • Authorization Filter
    用於檢查Request授權檢查的Filter,也是所有Filter第一個被執行的。
  • Resource Filter
    執行順序在 Authorization 之後,Model Binding 之前執行,用作對 Model 加工處理。
  • Action Filter
    封包進出都會經過Action Filter,跟 Resource Filter 很類似,但不會經過 Model Binding。
  • Exception Filter
    異常處理的Filter,可以制定統一的HTTP回應機制。
  • Result Filter
    Request的最後一關、Response的第一關。

各種Filter的執行順序如下圖:

實作Filter

接著,按照5種Filter的順序來實作,我們聚焦在Filter的同步/非同步與宣告部分,而不實做內容,例如,Authorization Filter,會提出宣告同步與非同步的方式,但不實做JWT或Oauth。

Authorization Filter

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

namespace CookbookApi.Filters
{
    public class AuthFilter : IAuthorizationFilter, IAsyncAuthorizationFilter
    {
        // 同步方法
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            // ...
        }

        // 非同步方法
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            // ... await
        }
    }
}

Resource Filter

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

namespace CookbookApi.Filters
{
    public class ResourceFilter : IResourceFilter, IAsyncResourceFilter
    {
        // 同步方法 - 執行完成後
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            // ...
        }

        // 同步方法 - 執行前
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            // ...
        }

        // 非同步方法 - 執行中
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            // ... await next();
        }
    }
}

Action Filter

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

namespace CookbookApi.Filters
{
    public class ActionFilter : IActionFilter, IAsyncActionFilter
    {
        // 同步方法 - 執行完成後
        public void OnActionExecuted(ActionExecutedContext context)
        {
            // ...
        }

        // 同步方法 - 執行前
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // ...
        }

        // 非同步方法 - 執行中
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // ... await next();
        }
    }
}

Exception Filter – 同步

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

namespace CookbookApi.Filters
{
    public class ExceptionFilter : IExceptionFilter, IAsyncExceptionFilter
    {
        // 同步方法
        public void OnException(ExceptionContext context)
        {
            // ... 
        }

        // 非同步方法
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            // ... await
        }
    }
}

Result Filter – 同步

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

namespace CookbookApi.Filters
{
    public class ResultFilter : IResultFilter, IAsyncResultFilter
    {
        // 同步方法 - 執行完成後
        public void OnResultExecuted(ResultExecutedContext context)
        {
            // ... 
        }

        // 同步方法 - 執行前
        public void OnResultExecuting(ResultExecutingContext context)
        {
            // ... 
        }

        // 非同步方法 - 執行中
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {
            // ... await next();
        }
    }
}

註冊Filter

全域註冊:在Startup.cs中的ConfigureServices中加入註冊的方法。

// ...
public void ConfigureServices(IServiceCollection services)
{
    // ...
    // 註冊的順序不代表執行順序,還是依照系統的規定運作
    services.AddMvc(config =>{
        config.Filters.Add(new Filters.AuthFilter());
        config.Filters.Add(new Filters.ResourceFilter());
        config.Filters.Add(new Filters.ActionFilter());
        config.Filters.Add(new Filters.ExceptionFilter());
        config.Filters.Add(new Filters.ResultFilter());
    });
}

區域註冊:若要註冊Filters.ActionFilter,可以在Controller中的任一個函數加入標籤[TypeFilter(typeof(Filters.ActionFilter))],如下所示:

// 區域註冊Filter
[TypeFilter(typeof(Filters.ActionFilter))]
// 區域註冊Middleware
[MiddlewareFilter(typeof(Middleware.ReqHeaderChecker))]
// 設定這個API使用HEAD方法
[HttpHead]
// 設定這個API使用GET方法
[HttpGet]
public IActionResult Get()
{
    // 宣告一個食譜的Model,並呼叫Libs.Recipe.Get函數取得資料
    Models.Resipe objResipe = Libs.Recipe.Get();
    // 回傳HTTP 200,內容為糖醋排骨的食譜資料
    return Ok(objResipe);
}

若標籤[TypeFilter(typeof(Filters.ActionFilter))]放在最外層的class,那表示這整個Controller都會套用這個Filter。

~ END ~


, ,

Related posts

Latest posts