ASP.NET Core實現中間件的幾種方式
前言
ASP.NET Core 中 HTTP 管道使用中間件組合處理的方式,
換句人話來說,
對于寫代碼的人而言,一切皆中間件.
業務邏輯/數據訪問/等等一切都需要以中間件的方式來呈現.
那么我們必須學會如何實現自定義中間件 這里劃重點,必考
這里我們介紹下中間件的幾種實現方式...
匿名函數
通常新建一個空的 ASP.NET Core Web Application,項目名字無所謂啦
在啟動類里可以看到這么一句:
// Startup.cs// ...app.Run(async (context) =>{ await context.Response.WriteAsync("Hello World!");});// ...
這就是一個匿名函數實現的中間件,雖然內容比較少.
可以看到通過匿名函數實現的中間件是內嵌在啟動類文件中的,因此通常也叫做內聯中間件
接下來,我們通過匿名函數來實現內聯中間件,以便加深理解.
然后修改啟動類代碼如下:
// Startup.csusing Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.DependencyInjection;using System;namespace WebApplication1{ public class Startup {public void ConfigureServices(IServiceCollection services){}public void Configure(IApplicationBuilder app, IHostingEnvironment env){ if (env.IsDevelopment()) {app.UseDeveloperExceptionPage(); } // 使用匿名函數實現一個內聯中間件 app.Use(async (context, next) => {throw new NotImplementedException("一個使用匿名函數,但未實現具體內容的內聯中間件"); }); app.Run(async (context) => {await context.Response.WriteAsync("Hello World!"); });} }}
這里我們在 app.Run
之前使用 app.Use
添加一個匿名函數實現的內聯中間件,按照中間件的注冊順序,當發起請求時,會拋出一個異常 NotImplementedException("一個使用匿名函數,但未實現具體內容的內聯中間件")
我們 F5 啟動下,看看頁面
嗯,符合預期.
我們再來調整下啟動類,代碼如下:
using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.DependencyInjection;namespace WebApplication1{ public class Startup {public void ConfigureServices(IServiceCollection services){}public void Configure(IApplicationBuilder app, IHostingEnvironment env){ if (env.IsDevelopment()) {app.UseDeveloperExceptionPage(); } // 使用匿名函數實現一個內聯中間件 app.Use(async (context, next) => {// 這里不對 request 做任何處理,直接調用下一個中間件await next.Invoke(); }); app.Run(async (context) => {await context.Response.WriteAsync("Hello World!"); });} }}
這里我們在 app.Run
之前使用 app.Use
添加一個匿名函數實現的內聯中間件,該中間件沒有對 request 做任何處理,只是一個空的空間件,按照中間件的注冊順序,當發起請求時,頁面應該顯示 Hello World!
.
我們 F5 啟動,看看效果
嗯,符合預期.
個人覺得:匿名函數不是很直觀,但是用內聯的方式可以快速開始一些開發,不用新建一個中間件類,不用專門想個不一樣的名字,小場景下是非常方便實用的
實現接口
通過實現接口 IMiddleware
編寫自定義中間件,這是一種強類型的方式,我們需要必須強制按照接口的定義來實現.
IMiddleware
接口 IMiddleware 定義如下:
using System.Threading.Tasks;namespace Microsoft.AspNetCore.Http{ public interface IMiddleware {Task InvokeAsync(HttpContext context, RequestDelegate next); }}
可以看到接口 IMiddleware 的命名空間是 Microsoft.AspNetCore.Http
,需要實現的方法是InvokeAsync()
,看起來不算太復雜, 嗯,看起來不算太復雜
嗯,重新開始,我們新建一個空的 ASP.NET Core Web Application
然后我們通過實現接口的方式來自定義一個中間件,代碼如下:
// 新建類 MyMiddleware.csusing Microsoft.AspNetCore.Http;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;namespace WebApplication1{ public class MyMiddleware : IMiddleware {public Task InvokeAsync(HttpContext context, RequestDelegate next){ throw new NotImplementedException();} }}
按照上面實現的中間件 MyMiddleware
,在執行時應該會拋出 NotImplementedException
.
使用接口實現的中間件需要在先在服務容器中注冊
// Startup.csusing Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.DependencyInjection;namespace WebApplication1{ public class Startup {public void ConfigureServices(IServiceCollection services){ // 在服務容器中注冊自定義中間件 services.AddSingleton<MyMiddleware>();}public void Configure(IApplicationBuilder app, IHostingEnvironment env){ if (env.IsDevelopment()) {app.UseDeveloperExceptionPage(); } // 使用 UseMiddleware() 把自定義中間件添加到管道中 app.UseMiddleware<MyMiddleware>(); app.Run(async (context) => {await context.Response.WriteAsync("Hello World!"); });} }}
然后 F5 啟動,頁面上可以看到如下結果:
符合我們上面的預期,拋出了一個 NotImplementedException
.
然后我們改造下 MyMiddleware
中間件
// MyMiddleware.csusing Microsoft.AspNetCore.Http;using System.Threading.Tasks;namespace WebApplication1{ public class MyMiddleware : IMiddleware {public async Task InvokeAsync(HttpContext context, RequestDelegate next){ // 這里不對 request 做任何處理,直接調用下一個中間件 await next(context);} }}
這里相當于我們實現了一個叫做 MyMiddleware
的中間件,但是并沒有對請求進行任何處理,頁面上應該正常顯示 Hello World!
字符串.
然后我們 F5 啟動看看
嗯...符合預期.
個人覺得:這種方式最符合面向對象的特性,也符合面向接口的原則,少一些難以理解的魔法,反而有助于理解.
約定方式
編程世界有這么一句話,叫"約定大于配置".
那么編寫中間件的約定是什么呢?
重新開始,新建一個空的 ASP.NET Core Web Application
然后新建一個類,類名叫做 MyMiddleware
好了,代碼如下:
// MyMiddleware.csusing Microsoft.AspNetCore.Http;using System;using System.Threading.Tasks;namespace WebApplication1{ public class MyMiddleware {// 1. 需要實現一個構造函數,參數為 RequestDelegatepublic MyMiddleware(RequestDelegate next){}// 2. 需要實現一個叫做 InvokeAsync 方法public async Task InvokeAsync(HttpContext context){ throw new NotImplementedException("這是一個按照約定方式編寫的中間件,但未實現具體內容");} }}
約定的內容,就是滿足2個需要...不滿足需要則異常.
然后我們把這個中間件,注冊到管道中,以便使用
// Startup.csusing Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.DependencyInjection;namespace WebApplication1{ public class Startup {public void ConfigureServices(IServiceCollection services){}public void Configure(IApplicationBuilder app, IHostingEnvironment env){ if (env.IsDevelopment()) {app.UseDeveloperExceptionPage(); } // 注冊自定義中間件 // 注冊順序=1 app.UseMiddleware<MyMiddleware>(); app.Run(async (context) => {await context.Response.WriteAsync("Hello World!"); });} }}
然后 F5 啟動,來看看效果
嗯,符合預期.
然后我們來調整下中間件,讓請求能正常響應輸出 Hello World!
using Microsoft.AspNetCore.Http;using System;using System.Threading.Tasks;namespace WebApplication1{ public class MyMiddleware {private readonly RequestDelegate _next;// 需要實現一個構造函數,參數為 RequestDelegatepublic MyMiddleware(RequestDelegate next){ _next = next;}// 需要實現一個叫做 InvokeAsync 方法public async Task InvokeAsync(HttpContext context){ // 不處理任何 request, 直接調用下一個中間件 await _next.Invoke(context);} }}
然后 F5 啟動,看看效果
嗯,符合預期.
個人覺得:只能說一句,約定方式是目前用的最多的方式...
End
寫在最后
Tips: 有些內容可能看起來還是不太容易理解,至少當下你是很難理解的,但是套路就在哪里,好比1+1=2,你知道1+1為什么=2么?但你一定會算會用1+1=2...
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章:
1. asp.net core項目授權流程詳解2. 關于Jenkins + Docker + ASP.NET Core自動化部署的問題(避免踩坑)3. ASP.Net Core(C#)創建Web站點的實現4. python使用tkinter實現屏幕中間倒計時5. asp.net core 中的Jwt(Json Web Token)的使用詳解6. Django日志及中間件模塊應用案例7. ASP.NET Core 依賴注入生命周期示例詳解8. uniapp 手機驗證碼輸入框實現代碼(隨機數、倒計時、隱藏手機號碼中間四位)可以直接使用9. ASP.NET Core依賴注入DI容器的方法實現10. 如何使用ASP.NET Core 配置文件