<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Jackyfei

      定制.NET 6.0的Middleware中間件

      大家好,我是張飛洪,感謝您的閱讀,我會不定期和你分享學習心得,希望我的文章能成為你成長路上的墊腳石,讓我們一起精進。

      本章是《定制ASP NET 6.0框架系列文章》的第8篇。在本文中,我們將學習中間件,以及如何使用它進一步定制應用程序。我們將快速學習中間件的基礎知識,然后探討如何使用它做的一些特殊事情。
      本文涵蓋的主題包括:

      • 中間件簡介
      • 編寫自定義中間件
      • 中間件的潛力
      • 如何使用中間件

      本章所處的位置,如下圖所示:

      技術準備

      我們使用控制臺、shell或Bash終端先創建一個ASP.NET Core MVC應用程序,然后切換到工作目錄:

      dotnet new web -n MiddlewaresDemo -o MiddlewaresDemo
      

      然后用VS打開項目:

      cd MiddlewaresDemo code .
      

      注意在.NET 6.0中,web項目模板發生了變化。Microsoft引入了minimal API,項目模板默認使用minimal API。

      中間件簡介

      大多數人可能已經知道中間件是什么,但有些人可能不知道,即使你已經在使用ASP.NET Core有一段時間了。我們一般不需要詳細了解中間件實例,因為它們大多隱藏在擴展方法后面,例如UseMvc()、UseAuthentication()、UseDeveloperExceptionPage()等。每次在Configure方法中,我們默認將隱式地使用至少一個或更多個中間件組件。

      中間件組件是處理請求管道的一段代碼。我們可以將請求流程想象成一串管道,每次請求調用,都會返回一個響應。中間件負責創建回聲——它操縱請求上下文,加工處理、疊加邏輯、豐富信息。

      中間件組件按配置順序執行。配置的第一個中間件組件是第一個執行的組件。我們可以把中間件看成回旋鏢,出去的時候第一個執行,回來的時候最后一個執行。

      在ASP.NET Core web應用程序,如果客戶端請求的是圖像或任何其他靜態文件,StaticFileMiddleware將負責查找該資源,如果找到該資源,則返回該資源。如果沒有,這個中間件除了調用下一個之外什么都不做。

      MvcMiddleware組件檢查請求的資源,將其映射到已配置的路由,執行控制器,創建視圖,并返回HTML或Web API結果。如果MvcMiddleware沒有找到匹配的控制器,它無論如何都會返回一個結果——通常是一個404狀態的結果,這就是為什么MvcMiddleware是最后配置的中間件。

      異常處理中間件通常是配置的第一批的中間件之一,不是因為它是第一個執行的,而是因為它是最后一個執行的。異常處理驗證結果,并以客戶端友好的方式在瀏覽器中顯示可能的異常。以下過程描述了運行時發生的500錯誤狀態:

      var builder = WebApplication.CreateBuilder(args); 
      var app = builder.Build(); 
      app.MapGet("/", () => "Hello World!"); 
      app.Run();
      

      在ASP.NET Core 6.0,Microsoft引入了minimal API,它簡化了應用配置,并隱藏了許多默認配置,比如隱式的using聲明,因此,在頭部我們看不到任何using語句,以上就是我們看到的ASP.NET Core 6.0中的Program.cs 文件內容。
      在這里,lambda中間件綁定到默認路由,只有一句簡單的“Hello World!”響應流。這個特殊的中間件會終止管道并返回響應內容。因此,它是最后一個運行的中間件。

      下面我們把app.MapGet()做個替換,如下所示:

      app.Use(async (context, next) =>{     
          await context.Response.WriteAsync("===");     
          await next();     
          await context.Response.WriteAsync("==="); 
      }); 
      app.Use(async (context, next) => { 
          await context.Response.WriteAsync(">>>>>> ");     
          await next();     
          await context.Response.WriteAsync(" <<<<<<");
      }); 
      app.Run(async context => { 
          await context.Response.WriteAsync("Hello World!"); 
      });
      
      

      這里調用兩個app.Use()方法,并且創建了兩個lambda中間件,除了做簡單的處理外,中間件還調用了它們的后繼組件,每個中間件的調用鏈很明確很清晰。在調用下一個中間件之前,處理實際的請求,在調用下個中間件之后,處理響應。以上就是管道的工作機制。
      如果現在運行程序(使用dotnet run)并在瀏覽器中打開URL,我們應該會看到這樣的純文本結果

      ===>>>>>> Hello World! <<<<<<===
      

      不知道您理解了沒?如果理解了,我們往下學習,看看如何使用這個概念向請求管道添加一些附加功能。

      編寫自定義中間件

      中間件可以說是ASP.NET Core的基座,在請求期間執行的所有邏輯都基于此機制。因此,我們可以使用它向web添加自定義功能。在下面案例,我們希望找出通過請求管道的每個請求的執行時間:

      我們可以在調用下一個中間件之前創建并啟動秒表,然后在調用下個中間件之后停止測量執行時間,如下所示:

      app.Use(async (context, next) => {     
          var s = new Stopwatch();     
          s.Start();     
          //其他操作 
          await next();     
          s.Stop(); 
          //結束度量     
          var result = s.ElapsedMilliseconds;     
          //統計耗時     
          await context.Response.WriteAsync($"耗時:{result} 秒。"); 
      });
      
      

      記得為System.Diagnostics添加using語句。
      之后,我們將經過的毫秒返回到響應流。
      如果您編寫的中間件組件很多,Program.cs將變得非常混亂。所以大多數中間件組件將被編寫為獨立的類,如下所示:

      using System.Diagnostics; 
      public class StopwatchMiddleware {    
          private readonly RequestDelegate _next;     
          public StopwatchMiddleware(RequestDelegate next)  
          {  
              _next = next;  
          }     
      
          public async Task Invoke(HttpContext context) {         
              var s = new Stopwatch();         
              s.Start();         
              //其他操作          
              await _next(context);         
              s.Stop(); 
              //結束度量         
              var result = s.ElapsedMilliseconds;         
              //統計耗時     
              await context.Response.WriteAsync($"耗時:{result} 秒。");    
          }  
      }
      

      在Invoke方法中的,我們獲得構造函數和當前上下文獲得要執行的下一個中間件組件。

      注意:
      中間件在應用程序啟動時初始化,構造函數在應用程序生命周期內僅運行一次。另一方面,每個請求調用一次Invoke方法。
      要使用此中間件,您可以使用一個通用的UseMiddleware方法:

      app.UseMiddleware<StopwatchMiddleware>();
      

      然而,更優雅的方法是創建一個封裝此調用的擴展方法:

      public static class StopwatchMiddlewareExtension {     
          public static IApplicationBuilder  UseStopwatch(this IApplicationBuilder app)     
          {         
              app.UseMiddleware<StopwatchMiddleware>();         
              return app;    
           }
       }
      
      

      然后就可以這樣使用:

      app.UseStopwatch();
      

      這樣,您可以通過請求管道向ASP.NET Core應用程序提供其他功能。中間件中提供了整個HttpContext。這樣,您可以使用中間件操縱請求和響應。

      例如,AuthenticationMiddleware嘗試從請求中收集用戶信息。如果找不到任何信息,它將通過向客戶端發送特定的響應來請求信息。如果它找到,它會將其添加到請求上下文中,并以這種方式將其提供給整個應用程序。

      中間件的潛力

      使用中間件還可以做許多其他事情。例如,可以將請求管道拆分為兩個或多個管道,我們將在這里討論如何做到這一點。

      使用/map分支管道

      下一段代碼顯示了如何基于特定路徑創建請求管道的分支:

      app.Map("/map1", app1 => {     
          // 其他中間件     
          app1.Run(async context =>     {         
                  await context.Response.WriteAsync("Map Test 1");     
          }); 
      }); 
      app.Map("/map2", app2 => {     
           // 其他中間件     
          app2.Run(async context => {         
              await context.Response.WriteAsync("Map Test 2");     
          }); 
      }); 
      // 其他中間件
      
      

      /map1路徑是一個特定的分支,它在內部繼續請求管道,/map2與此相同。這兩個map都有自己內部的中間件配置。所有其他未指定的路徑都遵循該主分支。

      使用MapWhen分支管道

      還有一個MapWhen方法可以根據條件分支管道,而不是根據路徑分支:

      public void Configure(IApplicationBuilder app) {     
          app.MapWhen(context =>context.Request.Query.ContainsKey("分支"),         
              app1 => {            
                   // 其他中間件           
                  app1.Run(async context =>  {  
                      await context.Response.WriteAsync( "MapBranch Test"); 
                  });     
          });     
          //其他中間件     
          app.Run(async context =>    { 
              await context.Response.WriteAsync("Hello non-Map.");     
          });
      }
      

      使用中間件構造條件

      我們一般可以根據配置值創建條件,或者根據請求上下文的屬性創建條件。在前面的示例中,我們使用了查詢字符串屬性作為條件。當然,你也可以使用HTTP標頭、表單屬性或請求上下文的任何其他屬性。

      如果需要,還可以嵌套map以創建子分支和孫分支。
      我們再看下健康檢查中間件,ASP.NET Core HealthCheck API的工作原理如下:
      首先,它使用MapWhen指定要使用的端口,然后,它使用Map設置HealthCheck API路徑(如果未指定端口則使用Map)。最后,使用了HealthCheckMiddleware。我們看下面的代碼示例:

      private static void UseHealthChecksCore(IApplicationBuilder app, PathString path, int? port, object[] args) 
      {     
          if (port == null)    
          {         
              app.Map(path, b => b.UseMiddleware<HealthCheckMiddleware>(args)); 
          }     
          else  {        
              app.MapWhen(c => c.Connection.LocalPort == port,
                  b0 => b0.Map(path, b1 =>b1.UseMiddleware<HealthCheckMiddleware>(args)));     
          }; 
      }
      
      

      這里,我們可以使用Map或MapWhen分別基于特定路徑或特定條件提供特殊的API或資源。
      接下來,讓我們看看如何在更新版本的ASP.NET Core中使用終止中間件組件。

      在ASP.NET Core 3.0及更高版本中使用中間件

      ASP.NET Core 3.0及更高版本,有兩種新的中間件,它們被稱為UseRoutingUseEndpoints

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {     
          if (env.IsDevelopment())     
          {  
              app.UseDeveloperExceptionPage();     
          }     
          app.UseRouting();     
          app.UseEndpoints(endpoints =>  {         
              endpoints.MapGet("/", async context => { 
                  await context.Response.WriteAsync("Hello  World!");         
              });     
          }); 
      }
      

      第一個是使用路由的中間件UseRouting,另一個是訪問地址的UseEndpoints

      這是新的端點路由。以前,路由是MVC的一部分,它只適用于MVC、Web API和基于MVC的框架。然而在ASP.NET Core 3.0及更高版本,路由不再是MVC框架中的一部分。現在,MVC和其他框架都可以被映射到特定的路由或端點。
      在前面的代碼段中,GET請求被映射到頁面根URL。在下一個代碼片段中,MVC被映射到路由模式,RazorPages被映射到基于RazorPage的特定文件結構的路由:

      app.UseEndpoints(endpoints => {     
          endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); 
          endpoints.MapRazorPages(); 
      });
      

      現在已經沒有UseMvc方法了,即使它仍然存在并在IApplicationBuilder對象級別上工作,以防止現有代碼中斷?,F在,激活ASP.NET Core功能的方法更為精細。

      • Areas for MVC and web APIendpoints.MapAreaControllerRoute(...);
      • MVC and web APIendpoints.MapControllerRoute(...);
      • Blazor server-sideendpoints.MapBlazorHub(...);
      • SignalRendpoints.MapHub(...);
      • Razor Pagesendpoints.MapRazorPages(...);
      • Health checksendpoints.MapHealthChecks(...);

      這些是ASP最常用的新Map方法。
      還有很多方法可以定義回退地址,比如將路由和HTTP方法映射到代理,以及中間件組件。
      你可以創建適用于所有請求的中間件,例如StopWatchMiddleware,你也可以編寫中間件以在特定路徑或路由上工作,例如創建一個Map方法,以將其映射到該路由。

      注意事項
      不再建議在中間件內部處理路由。相反,您應該使用新的地址路由。使用這種方法,中間件更加通用,它可以通過單一的配置就可以在多個路由上工作。

      重寫終止中間件

      接下來,我們創建小型虛擬中間件,將應用程序狀態寫入特定路由。在此示例中,沒有自定義路由處理:

      namespace MiddlewaresSample; 
      public class AppStatusMiddleware {     
          private readonly RequestDelegate _next;     
          private readonly string _status;
          public AppStatusMiddleware(RequestDelegate next, string status)     
          {        
              _next = next;         
              _status = status;    
          }     
          public async Task Invoke(HttpContext context)  {         
              await context.Response.WriteAsync($"Hello {_status}!");     
          } 
      }
      

      我們需要做的是在IEndpointRouteBuilder對象上編寫一個擴展方法。此方法將路由模式作為可選參數,并返回IEndpointConventionBuilder對象以啟用跨域資源共享(CORS)、身份驗證或路由的其他條件。

      現在,我們應該添加一個擴展方法,以便更容易地使用中間件:

      public static class MapAppStatusMiddlewareExtension {     
          public static IEndpointConventionBuilder MapAppStatus(this IEndpointRouteBuilder routes, string pattern = "/", string name = "World") 
           {         
              var pipeline = routes.CreateApplicationBuilder().UseMiddleware<AppStatusMiddleware>(name).Build();         
              return routes.Map(pattern, pipeline).WithDisplayName("AppStatusMiddleware");     
          } 
      }
      

      完成后,我們可以使用MapAppStatus方法將其映射到特定路線:

      app.UseRouting(); 
      app.UseEndpoints(endpoints => {     
          endpoints.MapGet("/", () => "Hello World!");     
          endpoints.MapAppStatus("/status", "Status"); 
      });
      

      現在,我們可以通過輸入以下地址在瀏覽器中調用路由: http://localhost:5000/status

      總結

      大多數ASP.NET Core功能基于中間件,在本章中,我們學習了中間件的工作原理以及如何創建自己的中間件組件來擴展ASP.NET框架。我們還學習了如何使用新路由向自定義的終止中間件添加路由。

      在下一章中,我們將了解ASP.NET Core中的新端點路由,它允許我們以簡單靈活的方式創建自己的托管端點。

      posted @ 2022-12-19 09:58  張飛洪[廈門]  閱讀(3612)  評論(8)    收藏  舉報
      主站蜘蛛池模板: 在线 欧美 中文 亚洲 精品| 日韩大片看一区二区三区| 男人天堂亚洲天堂女人天堂| 日本欧美大码a在线观看| 扒开双腿疯狂进出爽爽爽| 一级片黄色一区二区三区| 99久久精品费精品国产一区二| 深夜视频国产在线观看| 国产又色又爽又黄的视频在线 | av在线播放观看国产| 美女黄网站人色视频免费国产| 亚洲精品视频免费| 亚洲精品无码你懂的| 国产一级av在线播放| 国产成年码av片在线观看| 国产资源精品中文字幕| 国产美女被遭强高潮免费一视频| 波多野结衣免费一区视频| 亚洲一区二区在线av| 中文字幕少妇人妻精品| 最近中文字幕国产精选| 国产乱人伦真实精品视频| 亚洲综合在线日韩av| 99久久免费精品色老| 波多野42部无码喷潮| 精品国精品国自产在国产| 40岁大乳的熟妇在线观看| 中文字幕理伦午夜福利片| 亚洲无av在线中文字幕| 高清性欧美暴力猛交| 国产精品熟妇视频国产偷人| 龙门县| 四虎国产精品永久在线下载| 国产美女久久久亚洲综合| 无码人妻丰满熟妇区毛片18| 美腿丝袜亚洲综合第一页| 在线人人车操人人看视频| 国产高清亚洲一区亚洲二区| 普陀区| 亚洲熟妇中文字幕五十路| 亚洲a人片在线观看网址|