日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 中间件(Middleware)详解

發(fā)布時間:2024/4/15 asp.net 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 中间件(Middleware)详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
ASP.NET Core 中間件(Middleware)詳解 原文:ASP.NET Core 中間件(Middleware)詳解

本文為官方文檔譯文,官方文檔現(xiàn)已非機器翻譯 https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-2.1

什么是中間件(Middleware)?

中間件是組裝到應用程序管道中以處理請求和響應的軟件。 每個組件:

  • 選擇是否將請求傳遞給管道中的下一個組件。
  • 可以在調(diào)用管道中的下一個組件之前和之后執(zhí)行工作。

請求委托(Request delegates)用于構建請求管道,處理每個HTTP請求。

請求委托使用Run,Map和Use擴展方法進行配置。單獨的請求委托可以以內(nèi)聯(lián)匿名方法(稱為內(nèi)聯(lián)中間件)指定,或者可以在可重用的類中定義它。這些可重用的類和內(nèi)聯(lián)匿名方法是中間件或中間件組件。請求流程中的每個中間件組件都負責調(diào)用流水線中的下一個組件,如果適當,則負責鏈接短路。

將HTTP模塊遷移到中間件解釋了ASP.NET Core和以前版本(ASP.NET)中的請求管道之間的區(qū)別,并提供了更多的中間件示例。

使用 IApplicationBuilder 創(chuàng)建中間件管道

ASP.NET Core請求流程由一系列請求委托組成,如下圖所示(執(zhí)行流程遵循黑色箭頭):

每個委托可以在下一個委托之前和之后執(zhí)行操作。委托還可以決定不將請求傳遞給下一個委托,這稱為請求管道的短路。短路通常是可取的,因為它避免了不必要的工作。例如,靜態(tài)文件中間件可以返回一個靜態(tài)文件的請求,并使管道的其余部分短路。需要在管道早期調(diào)用異常處理委托,因此它們可以捕獲后面管道的異常。

最簡單的可能是ASP.NET Core應用程序建立一個請求的委托,處理所有的請求。此案例不包含實際的請求管道。相反,針對每個HTTP請求都調(diào)用一個匿名方法。

using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http;public class Startup {public void Configure(IApplicationBuilder app){app.Run(async context =>{await context.Response.WriteAsync("Hello, World!");});} }

第一個 app.Run 委托終止管道。

有如下代碼:

通過瀏覽器訪問,發(fā)現(xiàn)確實在第一個app.Run終止了管道。

您可以將多個請求委托與app.Use連接在一起。 next參數(shù)表示管道中的下一個委托。 (請記住,您可以通過不調(diào)用下一個參數(shù)來結束流水線。)通常可以在下一個委托之前和之后執(zhí)行操作,如下例所示:

public class Startup {public void Configure(IApplicationBuilder app){app.Use(async (context, next) =>{await context.Response.WriteAsync("進入第一個委托 執(zhí)行下一個委托之前\r\n");//調(diào)用管道中的下一個委托await next.Invoke();await context.Response.WriteAsync("結束第一個委托 執(zhí)行下一個委托之后\r\n");});app.Run(async context =>{await context.Response.WriteAsync("進入第二個委托\(zhòng)r\n");await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");await context.Response.WriteAsync("結束第二個委托\(zhòng)r\n");});} }

使用瀏覽器訪問有如下結果:

可以看出請求委托的執(zhí)行順序是遵循上面的流程圖的。

注意:
響應發(fā)送到客戶端后,請勿調(diào)用next.Invoke。 響應開始之后,對HttpResponse的更改將拋出異常。 例如,設置響應頭,狀態(tài)代碼等更改將會引發(fā)異常。在調(diào)用next之后寫入響應體。

  • 可能導致協(xié)議違規(guī)。 例如,寫入超過content-length所述內(nèi)容長度。

  • 可能會破壞響應內(nèi)容格式。 例如,將HTML頁腳寫入CSS文件。

HttpResponse.HasStarted是一個有用的提示,指示是否已發(fā)送響應頭和/或正文已寫入。

順序

在Startup。Configure方法中添加中間件組件的順序定義了在請求上調(diào)用它們的順序,以及響應的相反順序。 此排序?qū)τ诎踩?#xff0c;性能和功能至關重要。

Startup.Configure方法(如下所示)添加了以下中間件組件:

  • 異常/錯誤處理
  • 靜態(tài)文件服務
  • 身份認證
  • MVC
  • public void Configure(IApplicationBuilder app) {app.UseExceptionHandler("/Home/Error"); // Call first to catch exceptions// thrown in the following middleware.app.UseStaticFiles(); // Return static files and end pipeline.app.UseAuthentication(); // Authenticate before you access// secure resources.app.UseMvcWithDefaultRoute(); // Add MVC to the request pipeline. }

    上面的代碼,UseExceptionHandler是添加到管道中的第一個中間件組件,因此它捕獲以后調(diào)用中發(fā)生的任何異常。

    靜態(tài)文件中間件在管道中提前調(diào)用,因此可以處理請求和短路,而無需通過剩余的組件。 靜態(tài)文件中間件不提供授權檢查。 由其提供的任何文件,包括wwwroot下的文件都是公開的。

    如果請求沒有被靜態(tài)文件中間件處理,它將被傳遞給執(zhí)行身份驗證的Identity中間件(app.UseAuthentication)。 身份不會使未經(jīng)身份驗證的請求發(fā)生短路。 雖然身份認證請求,但授權(和拒絕)僅在MVC選擇特定的Razor頁面或控制器和操作之后才會發(fā)生。

    授權(和拒絕)僅在MVC選擇特定的Razor頁面或Controller和Action之后才會發(fā)生。

    以下示例演示了中間件順序,其中靜態(tài)文件的請求在響應壓縮中間件之前由靜態(tài)文件中間件處理。 靜態(tài)文件不會按照中間件的順序進行壓縮。 來自UseMvcWithDefaultRoute的MVC響應可以被壓縮。

    public void Configure(IApplicationBuilder app) {app.UseStaticFiles(); // Static files not compressedapp.UseResponseCompression();app.UseMvcWithDefaultRoute(); }

    Use, Run, 和 Map

    你可以使用Use,Run和Map配置HTTP管道。Use方法可以使管道短路(即,可以不調(diào)用下一個請求委托)。Run方法是一個約定, 并且一些中間件組件可能暴露在管道末端運行的Run [Middleware]方法。Map*擴展用作分支管道的約定。映射根據(jù)給定的請求路徑的匹配來分支請求流水線,如果請求路徑以給定路徑開始,則執(zhí)行分支。

    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:19219 的請求和響應:

    請求響應
    localhost:1234Hello from non-Map delegate.
    localhost:1234/map1Map Test 1
    localhost:1234/map2Map Test 2
    localhost:1234/map3Hello from non-Map delegate.

    當使用Map時,匹配的路徑段將從HttpRequest.Path中刪除,并為每個請求追加到Http Request.PathBase。

    MapWhen根據(jù)給定謂詞的結果分支請求流水線。 任何類型為Func<HttpContext,bool>的謂詞都可用于將請求映射到管道的新分支。 在以下示例中,謂詞用于檢測查詢字符串變量分支的存在:

    public class Startup {private static void HandleBranch(IApplicationBuilder app){app.Run(async context =>{var branchVer = context.Request.Query["branch"];await context.Response.WriteAsync($"Branch used = {branchVer}");});}public void Configure(IApplicationBuilder app){app.MapWhen(context => context.Request.Query.ContainsKey("branch"),HandleBranch);app.Run(async context =>{await context.Response.WriteAsync("Hello from non-Map delegate. <p>");});} }

    以下下表顯示了使用上面代碼 http://localhost:19219 的請求和響應:

    請求響應
    localhost:1234Hello from non-Map delegate.
    localhost:1234/?branch=1Branch used = master

    Map支持嵌套,例如:

    app.Map("/level1", level1App => {level1App.Map("/level2a", level2AApp => {// "/level1/level2a"//...});level1App.Map("/level2b", level2BApp => {// "/level1/level2b"//...});});

    Map也可以一次匹配多個片段,例如:

    app.Map("/level1/level2", HandleMultiSeg);

    內(nèi)置中間件

    ASP.NET Core附帶以下中間件組件:

    中間件描述
    Authentication提供身份驗證支持
    CORS配置跨域資源共享
    Response Caching提供緩存響應支持
    Response Compression提供響應壓縮支持
    Routing定義和約束請求路由
    Session提供用戶會話管理
    Static Files為靜態(tài)文件和目錄瀏覽提供服務提供支持
    URL Rewriting Middleware用于重寫 Url,并將請求重定向的支持

    編寫中間件

    中間件通常封裝在一個類中,并使用擴展方法進行暴露。 查看以下中間件,它從查詢字符串設置當前請求的Culture:

    public class Startup {public void Configure(IApplicationBuilder app){app.Use((context, next) =>{var cultureQuery = context.Request.Query["culture"];if (!string.IsNullOrWhiteSpace(cultureQuery)){var culture = new CultureInfo(cultureQuery);CultureInfo.CurrentCulture = culture;CultureInfo.CurrentUICulture = culture;}// Call the next delegate/middleware in the pipelinereturn next();});app.Run(async (context) =>{await context.Response.WriteAsync($"Hello {CultureInfo.CurrentCulture.DisplayName}");});} }

    您可以通過傳遞Culture來測試中間件,例如 http://localhost:19219/?culture=zh-CN

    以下代碼將中間件委托移動到一個類:

    using Microsoft.AspNetCore.Http; using System.Globalization; using System.Threading.Tasks;namespace Culture {public class RequestCultureMiddleware{private readonly RequestDelegate _next;public RequestCultureMiddleware(RequestDelegate next){_next = next;}public Task Invoke(HttpContext context){var cultureQuery = context.Request.Query["culture"];if (!string.IsNullOrWhiteSpace(cultureQuery)){var culture = new CultureInfo(cultureQuery);CultureInfo.CurrentCulture = culture;CultureInfo.CurrentUICulture = culture;}// Call the next delegate/middleware in the pipelinereturn this._next(context);}} }

    以下通過IApplicationBuilder的擴展方法暴露中間件:

    using Microsoft.AspNetCore.Builder;namespace Culture {public static class RequestCultureMiddlewareExtensions{public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder){return builder.UseMiddleware<RequestCultureMiddleware>();}} }

    以下代碼從Configure調(diào)用中間件:

    public class Startup {public void Configure(IApplicationBuilder app){app.UseRequestCulture();app.Run(async (context) =>{await context.Response.WriteAsync($"Hello {CultureInfo.CurrentCulture.DisplayName}");});} }

    中間件應該遵循顯式依賴原則,通過在其構造函數(shù)中暴露其依賴關系。 中間件在應用程序生命周期構建一次。 如果您需要在請求中與中間件共享服務,請參閱以下請求相關性。

    中間件組件可以通過構造方法參數(shù)來解析依賴注入的依賴關系。 UseMiddleware也可以直接接受其他參數(shù)。

    每個請求的依賴關系

    因為中間件是在應用程序啟動時構建的,而不是每個請求,所以在每個請求期間,中間件構造函數(shù)使用的作用域生命周期服務不會與其他依賴注入類型共享。 如果您必須在中間件和其他類型之間共享作用域服務,請將這些服務添加到Invoke方法的簽名中。 Invoke方法可以接受由依賴注入填充的其他參數(shù)。 例如:

    public class MyMiddleware {private readonly RequestDelegate _next;public MyMiddleware(RequestDelegate next){_next = next;}public async Task Invoke(HttpContext httpContext, IMyScopedService svc){svc.MyProperty = 1000;await _next(httpContext);} } posted on 2019-07-11 22:48 NET未來之路 閱讀(...) 評論(...) 編輯 收藏

    轉(zhuǎn)載于:https://www.cnblogs.com/lonelyxmas/p/11173306.html

    總結

    以上是生活随笔為你收集整理的ASP.NET Core 中间件(Middleware)详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。