.NET Core 3.0 中介軟體 Middleware
阿新 • • 發佈:2019-11-05
中介軟體官網文件解釋:中介軟體是一種裝配到應用管道以處理請求和響應的軟體 每個中介軟體:
- 選擇是否將請求傳遞到管道中的下一個元件。
- 可在管道中的下一個元件前後執行工作。
使用 IApplicationBuilder 建立中介軟體管道
ASP.NET Core 請求管道包含一系列請求委託,依次呼叫。 下圖演示了這一概念。 沿黑色箭頭執行。
IApplicationBuilder提供了三個擴充套件方法配置請求委託
- app.Run 作用新增一個終端中介軟體,因為不在向下傳遞請求,常常公開在管道末尾執行。例項程式碼
app.Run(async context => { await context.Response.WriteAsync("Hello, middleware!"); });
- app.Use 將多個請求委託連結在一起。next 引數表示管道中的下一個委託。 可通過不 呼叫 next 引數使管道短路等同於aap.run。 通常可在下一個委託前後執行操作,如以下示例所示:
app.Use(async (context, next) => { // 傳遞前操作 await next.Invoke(); // 傳遞前操作 }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); }
- Map 擴充套件用作約定來建立管道分支。 Map 基於給定請求路徑的匹配項來建立請求管道分支。 如果請求路徑以給定路徑開頭,則執行分支。例項程式碼如下
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>"); }); }
自定義中介軟體
以下演示記錄api輸入輸出引數的中介軟體。
1.建立一個webapi專案,在預設的WeatherForecastController控制器中新增一個簡單的post方法,程式碼如下
[HttpPost] public string PostWeatherForecast(int TemperatureC) { return "新增成功"; }
2.新建一箇中間件類.CS檔案如圖
選擇之後預設程式碼如下:
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project public class LogReqResponseMiddleware { private readonly RequestDelegate _next; public LogReqResponseMiddleware(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext httpContext) { return _next(httpContext); } } // Extension method used to add the middleware to the HTTP request pipeline. public static class LogReqResponseMiddlewareExtensions { public static IApplicationBuilder UseLogReqResponseMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<LogReqResponseMiddleware>(); } }
腳手架自動幫我們建立一個 Invoke方法,傳遞給下一個中介軟體。一個將自定義的中介軟體新增到了http請求管道的擴充套件方法UseLogReqResponseMiddleware。
上面invoke不是非同步的,我們自己可以改動,以下程式碼展示 一個api請求的輸入引數和輸出資訊的日誌列印
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project public class LogReqResponseMiddleware { private readonly RequestDelegate _next; public LogReqResponseMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext, ILogger<LogReqResponseMiddleware> logger) { var request = httpContext.Request; var buffer = new byte[Convert.ToInt32(request.ContentLength)]; await request.Body.ReadAsync(buffer, 0, buffer.Length); //把請求body流轉換成字串 var bodyAsText = Encoding.UTF8.GetString(buffer); //記錄請求資訊 var requestStr = $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}"; logger.LogDebug("Request:" + requestStr); var originalBodyStream = httpContext.Response.Body; using (var responseBody = new MemoryStream()) { httpContext.Response.Body = responseBody; await _next(httpContext); var response = httpContext.Response; response.Body.Seek(0, SeekOrigin.Begin); //轉化為字串 string text = await new StreamReader(response.Body).ReadToEndAsync(); //從新設定偏移量0 response.Body.Seek(0, SeekOrigin.Begin); //記錄返回值 var responsestr = $"{response.StatusCode}: {text}"; logger.LogDebug("Response:" + responsestr); await responseBody.CopyToAsync(originalBodyStream); } } } // Extension method used to add the middleware to the HTTP request pipeline. public static class LogReqResponseMiddlewareExtensions { public static IApplicationBuilder UseLogReqResponseMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<LogReqResponseMiddleware>(); } }
然後在Startup類的Configure方法中新增下面一行程式碼,把自定義的中間新增到了HTTP請求的管道中。
app.UseLogReqResponseMiddleware();//記錄http請求 輸入、輸出值;
我們在postman中模擬請求
控制檯上列印的資訊如下: