詳解C#如何自定義書寫中間件
一、什么是中間件
中間件是一種裝配到應(yīng)用管道以處理請求和響應(yīng)的軟件。是介于request與response處理過程之間的一個插件(一道處理過程),相對比較輕量級,并且在全局上會影響到request對象和response對象的屬性。因為改變的是全局,所以需要謹慎實用,用不好會影響到性能。每個組件:
1、選擇是否將請求傳遞到管道中的下一個組件。
2、可在管道中的下一個組件前后執(zhí)行工作。
原理圖:
多個中間件時,中間件請求和響應(yīng)的中間件順序相反
二、為什么使用中間件
在我們很多時候,當一個請求過來之后,我們想對這個請求做各種各樣的操作和記錄,這個時候我們可以加入中間件。目的就是對這個請求和響應(yīng)做處理,其實不難理解,這就是類似于工業(yè)機器,一個商品出來之前會有很多關(guān)卡,會執(zhí)行N到工序。最后加工出來的產(chǎn)品就是我們想要的,也是安全的。這些關(guān)卡就類似于中間件的作用了。
微軟約定中間件需要兩個參數(shù),一個是httpcontext上下文對象,一個是Task類型的委托。通過上下文對象,處理請求,通過委托傳遞上下文對象到下一個中間件。核心就是一系列的請求委托,Run、Use、Map
- Run:是最后一道工序,管道末尾。
- Use:連接請求委托,next 向下走。
- Map:擴展用作約定創(chuàng)建管道分支。
三、定義中間件
中間件的處理流程就像一個俄羅斯套娃,微軟約定中間件需要兩個參數(shù),一個是httpcontext上下文對象,一個是Task類型的委托。通過上下文對象,處理請求,通過委托傳遞上下文對象到下一個中間件,這也是套娃模式的由來。RequestDelegate是管道的核心。ApplicationBuilder就是接收了很多個RequestDelegae把它拼到一起。
定義
/// <summary> /// 中間件定義和業(yè)務(wù)邏輯 /// </summary> public class MyMiddleware { private readonly RequestDelegate _next; /// <summary> /// 構(gòu)造 /// </summary> /// <param name="next"></param> public MyMiddleware(RequestDelegate next) { _next = next; } /// <summary> /// 方法名必須命名為 Invoke或者 InvokeAsync,才能有效執(zhí)行下一個中間件 /// </summary> /// <param name="httpContext"></param> /// <returns></returns> public async Task InvokeAsync(HttpContext httpContext) { /* * 在這里可以書寫業(yè)務(wù)處理邏輯 *中間件的處理流程就像一個俄羅斯套娃,微軟約定中間件需要兩個參數(shù),一個是httpcontext上下文對象,一個是Task類型的委托。 * 通過上下文對象,處理請求,通過委托傳遞上下文對象到下一個中間件(這也是套娃模式的由來)。 */ try { await _next(httpContext); } catch (Exception ex) { //內(nèi)部出現(xiàn)異常 httpContext.Response.StatusCode = 500; } finally { var statusCode = httpContext.Response.StatusCode; var msg = ""; switch (statusCode) { case 401: msg = "未授權(quán)"; break; case 403: msg = "拒絕訪問"; break; case 404: msg = "未找到服務(wù)"; break; case 405: msg = "405 Method Not Allowed"; break; case 500: msg = "服務(wù)器內(nèi)部錯誤"; break; case 502: msg = "請求錯誤"; break; } if (!string.IsNullOrWhiteSpace(msg)) { await HandleExceptionAsync(httpContext, msg); } } } /// <summary> /// 處理Http響應(yīng)異常 /// </summary> /// <param name="httpContext"></param> /// <param name="msg"></param> /// <returns></returns> private async Task HandleExceptionAsync(HttpContext httpContext, string msg) { ErrorModel error = new ErrorModel { code = httpContext.Response.StatusCode, msg = msg }; var result = JsonConvert.SerializeObject(error); httpContext.Response.ContentType = "application/json;charset=utf-8"; await httpContext.Response.WriteAsync(result).ConfigureAwait(false); } }
封裝拓展方法
創(chuàng)建一個中間件拓展類,為每個自定義中間件創(chuàng)建方法,通過IApplicationBuilder拓展方法暴露
/// <summary> /// 中間件拓展類 /// </summary> public static class MyMiddlewareExtensions { /// <summary> /// 將封裝的中間件委托到一個類中,通過IApplicationBuilder拓展方法暴露 /// </summary> /// <param name="builder"></param> /// <returns></returns> public static IApplicationBuilder UseMyMiddlewareOne(this IApplicationBuilder builder) { return builder.UseMiddleware<MyMiddleware>(); } /* * 下面還可以拓展其他自定義中間件方法,通過IApplicationBuilder暴露 */ }
四、配置使用中間件
使用中間件
注意:使用中間件,順序非常重要。比如此處,要放在權(quán)限處理的前面。不然請求從管道回來的時候,會先走消息處理,然后再判斷權(quán)限,這樣的話就無法處理了。因為使用多個中間件時,中間件請求和響應(yīng)的順序是相反的,此處還是爬樓看上面的原理圖比較清晰。
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //開發(fā)環(huán)境使用 app.UseSwagger(); app.UseSwaggerUI(option => { foreach (string version in typeof(ApiVersions).GetEnumNames()) { option.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"版本:{version}"); } }); } app.UseRouting(); //使用自定義中間件: app.UseMyMiddlewareOne();//注冊自定義中間件 app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
五、演示
定義測試Http接口:
/// <summary> /// 自定義中間件測試 /// </summary> /// <param name="param"></param> /// <returns></returns> [HttpGet] public int MiddleWareTest(string param) { /* * note:此處的字符串是否是數(shù)字不做判斷,當輸入的非數(shù)字字符串時,強轉(zhuǎn)Int服務(wù)內(nèi)部會 */ int Number = int.Parse(param); return Number; }
Http請求測試:
到此這篇關(guān)于詳解C#如何自定義書寫中間件的文章就介紹到這了,更多相關(guān)C#中間件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
DevExpress之ChartControl用法實例總結(jié)
這篇文章主要介紹了DevExpress之ChartControl用法實例總結(jié),需要的朋友可以參考下2014-08-08利用C#與PLC通信實現(xiàn)設(shè)備遠程控制與管理
PLC是工業(yè)自動化中用于控制機械設(shè)備、生產(chǎn)線等的核心設(shè)備,通過與PLC的通信,我們可以實現(xiàn)設(shè)備的遠程監(jiān)控、數(shù)據(jù)采集等功能,C#作為一種現(xiàn)代化的編程語言,能夠非常方便地與PLC進行通信,本文將介紹如何利用C#與PLC進行通信,并實現(xiàn)設(shè)備的遠程控制與管理2025-02-02