1. 程式人生 > 其它 >.net core 5.0 之自定義中介軟體

.net core 5.0 之自定義中介軟體

微軟官方自定義中介軟體文件:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/write?view=aspnetcore-5.0#per-request-middleware-dependencies

1. 中介軟體的定義:(官方文件) https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0

  中介軟體是一種裝配到應用管道以處理請求和響應的軟體。 每個元件:     

    a. 選擇是否將請求傳遞到管道中的下一個元件。

               b. 可在管道中的下一個元件前後執行工作。

  請求委託用於生成請求管道。 請求委託處理每個 HTTP 請求。

  使用 RunMap 和 Use 擴充套件方法來配置請求委託。 可將一個單獨的請求委託並行指定為匿名方法(稱為並行中介軟體),或在可重用的類中對其進行定義。 這些可重用的類和並行匿名方法即為中介軟體,也叫中介軟體元件。 請求管道中的每個中介軟體元件負責呼叫管道中的下一個元件,或使管道短路。 當中間件短路時,它被稱為“終端中介軟體”,因為它阻止中介軟體進一步處理請求。

 

 

 

 

 

 

2.  管道中介軟體官方建議的執行順序

 

 

 3. 自定義中介軟體實現必須滿足兩點條件

      3.1. 具有型別為 RequestDelegate 的引數的公共建構函式。

      3.2. 名為 Invoke 或 InvokeAsync 的公共方法。 此方法必須:

            a. 返回 Task

            b.  接受型別 HttpContext 的第一個引數。

 4. 實現示例

             

public class CustomMiddleware
    {
        public string _msg;
        public RequestDelegate _requestDelegate;
        public CustomMiddleware(RequestDelegate requestDelegate, string msg)
        {
            _requestDelegate = requestDelegate;
            _msg = msg;
        }
        public async Task InvokeAsync(HttpContext httpContext)
        {
            Console.WriteLine(_msg);
           
            await _requestDelegate(httpContext);
        }
    }
public static class MiddlewareExtension
    {
        public static IApplicationBuilder Custom(this IApplicationBuilder app,string msg)
        {
            return app.UseMiddleware<CustomMiddleware>(msg);
        }
    }  
app.Custom("hello");

 

請求http://localhost:5000/之後的執行結果:

 

 

 

 5. 擴充套件資料:

.net core 都是通過 IApplicationBuilder 來新增中介軟體建立管道,所以中介軟體都是圍繞它來建立的。請求管道包含一系列請求委託,依次呼叫。每個委託均可在下一個委託前後執行操作。 應儘早在管道中呼叫異常處理委託,這樣它們就能捕獲在管道的後期階段發生的異常。

配置請求委託的幾種方式:

  • app.Use(): 將多個請求委託連結在一起,按照順序依次執行。 next 引數表示管道中的下一個委託。 可通過不呼叫 next 引數使管道短路。 通常可在下一個委託前後執行操作.       
public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

 

 

 

  •    app.Run():委託不會收到 next 引數。 第一個 Run 委託始終為終端,用於終止管道。如果在 Run 委託之後添加了另一個 Use 或 Run 委託,則不會呼叫該委託。
public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}
  •  app.map() : 用作約定來建立管道分支。 Map 基於給定請求路徑的匹配項來建立請求管道分支。 如果請求路徑以給定路徑開頭,則執行分支。
public class Startup
{
    private static void HandleMapTest1(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 1");
        });
    }

    private static void HandleMapTest2(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 2");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1", HandleMapTest1);

        app.Map("/map2", HandleMapTest2);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
        });
    }
}

  下表使用前面的程式碼顯示來自 http://localhost:1234 的請求和響應。

 

  •  app.MapWhen() : 基於給定前面的謂詞的結果來建立請求管道分支。

  MapWhen(this IApplicationBuilder app, Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration)簡單來說就是predicate如果為true則執行後面的configuration委託

  •  app.UseWhen() : 也基於給定謂詞的結果建立請求管道分支。 與 MapWhen 不同的是,如果這個分支不發生短路或包含終端中介軟體,則會重新加入主管道。