在.NET 6.0中自定義介面路由

2023-04-17 15:00:32

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

在本文中,我們將討論ASP.NET Core中的新路由。我們將瞭解什麼是介面(endpoints)路由,它是如何工作的,它在哪裡使用,以及如何建立自己的路由。

本文主題:

  • 探索介面路由
  • 建立自定義介面
  • 建立更復雜的介面

名詞定義:端點,即我們存取的介面或者叫API,有些地方叫EndPoint或者叫介面,其實源頭的稱呼應該叫端點會更貼切一些。或者你也可以直接叫EndPoint,但是先不管那麼多,大概瞭解這個意思就可以了。

探索介面路由

要了解介面路由(End Point),您需要了解什麼是端點以及什麼是路由。

端點是應用程式的一部分,當路由將傳入的請求對映到它時,端點就會被執行。

使用者端通常從伺服器請求資源。大多數情況下,使用者端是一個瀏覽器。資源由指向特定目標的URL定義。除了網頁,它也可以是一個移動應用程式,從Web API請求特定JSON資料。

另一方面,執行的端點被對映到一個特定的路由,ASP.NET Core開發人員已經熟悉這樣一種路由模式:

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

如果路由或路由模式與傳入請求的URL匹配,則請求將對映到該端點。
ASP.NET Core可以對映到以下端點:

  • Controllers (例如, MVC or web APIs)
  • Razor Pages
  • SignalR (and Blazor Server)
  • gRPC services
  • Health checks
    大多數端點都有非常簡單的路由模式。只有MVC和Web API端點使用更復雜的模式。Razor頁面的路由定義基於實際頁面的資料夾和檔案結構。

在ASP.NET Core 2.2中引入端點之前,路由只是運用在MVC和Web API中。Razor Pages中的隱式路由是內建的,SignalR沒有路由一說。Blazor和gRPC在當時還不不知道在哪兒,健康檢查最初是作為中介軟體元件實現的。

引入端點路由是為了將路由與實際端點分離,說得白話一點,就是讓URL地址和實際執行的Action進行分離,這會讓框架更加靈活,同時這意味著新的端點不需要實現自己的路由。

建立自定義介面

建立端點的最簡單方法是使用lambda:

app.Map("/map", async context => {  
    await context.Response.WriteAsync("OK"); 
});

這裡將/map路由對映到一個簡單的端點,該端點將單詞「OK」寫入響應流。

關於早期.NET 6.0版本的說明
.NET 6.0之前,該對映只能在Startup.cs檔案中的UseEndpoints方法中,而使用.NET 6.0和新的Minimal API方法,可以在Program.cs檔案中完成對映。

另外,我們需要將Microsoft.AspNetCore.Http名稱空間新增到using語句中。
還可以將特定的HTTP方法(如GET、POST、PUT和DELETE)對映到端點。以下程式碼顯示瞭如何對映GET和POST方法:

app.MapGet("/mapget", async context => {     
    await context.Response.WriteAsync("Map GET"); 
}); 
app.MapPost("/mappost", async context => {  
        await context.Response.WriteAsync("Map POST");
});

我們還可以將兩個或多個HTTP方法對映到一個端點:

app.MapMethods("/mapmethods",  new[] { "DELETE", "PUT" }, 
    async context => {
        await context.Response.WriteAsync("Map Methods");
});

這些端點對映很像我們在第8篇客製化.NET 6.0的Middleware中介軟體中看到的基於lambda的中介軟體元件,這些管道中介軟體會返回結果,例如基於HTML的檢視、JSON結構化資料或類似的內容。但是,端點路由是一種更靈活的輸出方式,它應該會在ASP.NET Core 3.0以後的所有版本中進行使用。

在第8篇中,我們看到我們可以像這樣的分支管道:

app.Map("/map", mapped => {     // ……  });

以上這種方式也會建立一個路由,但只會偵聽以/map開頭的URL。如果您希望有一個處理/map/{id:int?}等模式的路由引擎,來匹配/map/456而不是/map/abc,那麼您應該使用前面所述的新的路由。

而那些基於lambda的端點對映,對於簡單的場景非常有用。然而,由於它們是在Program.cs中定義的,如果您想使用這種方式來實現更復雜的場景,程式碼維護性將變得很差。

因此,我們應該嘗試找到一種更結構化的方法來建立自定義端點。

建立更復雜的介面

接下來,我們將建立一個健康檢查介面例子,有點類似於您在Kubernetes叢集中執行應用程式時可能需要的介面,用來檢測系統的健康狀態:
我們從開發者的角度定義API介面,我們首先新增一個MapMyHealthChecks方法,作為IEndpointRouteBuilder物件上的一個擴充套件方法,它沒有實現:

app.MapMyHealthChecks("/myhealth");   
app.MapControllerRoute(name: "default",pattern:"{controller=Home}/{action=Index}/{id?}");

為了避免混淆,我們這兒採取和之前類似的方式新增新介面,後面我們進一步來實現一下。
我們建立一個名為MapMyHealthChecksExtensions的靜態類,並在MapMyHealthCheck中放置一個擴充套件方法,該物件擴充套件IEndpointRouteBuilder介面並返回IEndpointConventionBuilder物件:

namespace RoutingSample; 
public static class MapMyHealthChecksExtensions {     
    public static IEndpointConventionBuilder  MapMyHealthChecks (this IEndpointRouteBuilder endpoints, string pattern = "/myhealth")     
    {         
        // ...     
    } 
}

以上只是骨架,實際的介面將被實現為一個終止的中介軟體,也就是說,它不呼叫下一個的中介軟體元件,並建立響應流的輸出:

namespace RoutingSample; 
public class MyHealthChecksMiddleware {     
    private readonly ILogger _logger;     
    public MyHealthChecksMiddleware (RequestDelegate next, ILogger logger)    
     {  
        _logger = logger;     
    }     

    public async Task Invoke(HttpContext context)     {         
        // add some checks here...         
        context.Response.StatusCode = 200;         
        context.Response.ContentType = "text/plain";         
        await context.Response.WriteAsync("OK");     
    } 
}

實際工作是在Invoke方法中完成的。目前,只演示200狀態碼和OK狀態響應,我們可以在這裡隨意擴充套件該方法,例如檢查資料庫或相關服務的可用性。

接下來我們使用這個終止中介軟體,我們回到MapMyHealthChecks方法的框架。我們現在建立一個自己的管道,並將其對映到給定的pipeline:

var pipeline = endpoints.CreateApplicationBuilder().UseMiddleware().Build(); 
return endpoints.Map(pattern, pipeline).WithDisplayName("My custom health checks");

這種方法允許我們為這個新的管道新增更多的中介軟體。WithDisplayName擴充套件方法將設定的顯示名稱設定為介面,接下來按F5鍵啟動程式,並在瀏覽器中呼叫https://localhost:7111/myhealth。我們將看到:

請注意,埠號可能會有所不同。我們還可以將已經存在的終止中介軟體元件轉換為路由介面,以設定更加靈活的路由。

總結

ASP.NET Core支援請求處理並向請求提供資訊的多種方法。介面路由是一種基於URL和請求的方法提供資源。
在本文,我們學習瞭如何使用終止中介軟體元件作為介面,並用將該介面對映到新的路由引擎,從而讓我們的路由變得更加強大和靈活。
每個Web應用程式都需要了解系統使用者,以允許或限制對特定資料的存取。在下一章中,我們將展示如何設定身份驗證和識別使用者。