iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
0
Modern Web

我與 ASP.NET Core 的 30天系列 第 10

[Day10] 路由(Routing)- 我與 ASP.NET Core 3 的 30天

路由的基本概念

所有 ASP.NET Core 範本都包含產生的程式碼中的路由。
基本路由是在Startup.Configure中的Middleware管線中註冊。(可參考[Day03] Middleware- 我與 ASP.NET Core 3 的 30天)

下列程式碼顯示路由的基本範例:

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註冊的Middleware:

  • UseRouting 會將路由對應新增到Middleware中。此Middleware會查看應用程式中定義的端點集合,並根據要求選取最符合的條件。
  • UseEndpoints 將端點執行新增至中介軟體管線。它會執行與所選端點相關聯的委派。

上述範例包含使用MapGet方法 ,將單一路由傳送至程式碼端點:

  • 當HTTP GET Request傳送到根URL("/")時:
    • 顯示的要求委派會執行
    • Hello World! 會寫入 HTTP Response
  • 如果要求方法不是 GET 或是根URL不是"/",則不符合任何路由,且會回傳HTTP 404

端點(Endpoint)

上方的範例中,MapGet方法就是用來定義端點。(Map的使用方法可參照[Day03] Middleware- 我與 ASP.NET Core 3 的 30天
端點可以是:

  • 選取此選項,藉由比對 URL 和 HTTP 方法。
  • 執行委派。

應用程式中可以比對和執行的端點會在UseEndpoints中設定。例如MapGet、MapPost、MapPut...等等方法會將要求委派連接至路由系統。
除了基本的路由設定之外,我們還可以在Controller及Action中設** 屬性路由 **

屬性路由(Attribute Routing)

屬性路由可以針對每個Controller及Action做自定義的路由,能夠讓作為端點的Action可以更彈性的做路由設計。

套用 Attribute在 Controller 類別

  • [Route("api/[controller]")]

套用 Attribute 在 Action 方法

  • [HttpGet("{id}")]
  • [HttpPost("")]
  • [HttpDelete("{id}")]
  • [HttpPut("{id}")]
  • [HttpPatch("{id}")]

適合用屬性路由的網址結構

  • 常見的 RESTful APIs 網址結構
    • /customers/1/orders
  • 在網址結構上標示 APIs 版本 (API versioning)
    • /api/v1/products
    • /api/v2/products
  • 重載的網址結構 (Overloaded URI segments)
    • /orders/1
    • /orders/pending
  • 多重參數型態 (Mulitple parameter types)
    • /orders/1
    • /orders/2013/06/16

下面就來示範如何設定屬性路由實現此路由
/customers/1/orders

public class OrdersController : ControllerBase 
{
    [HttpGet("customers/{customerId}/orders")]
    public IEnumerable<Order> FindOrdersByCustomer(int customerId) { ... } 
}

因為customerId必須為int,所以我們必須加上型別的限制

public class OrdersController : ControllerBase 
{
    [HttpGet("customers/{customerId:int}/orders")]
    public IEnumerable<Order> FindOrdersByCustomer(int customerId) { ... } 
}

屬性路由的參數還可以設定預設值或可選參數

public class OrdersController : ControllerBase 
{
    [HttpGet("{id:int=1}")]
    public IEnumerable<Order> Get(int id) { ... } 
}

或者設置為可選參數,並讓預設值加在傳入的參數中

public class OrdersController : ControllerBase 
{
    [HttpGet("{id:int?}")]
    public IEnumerable<Order> Get(int id = 1) { ... } 
}

Controller的前置詞

在API的Controller中,慣例都會加上 api/ 作為路由前置詞(Route Prefixes)後面再帶上Controller名稱
[Route("api/[controller]")],不過如果今天有某個Action不想要沿用這樣子的前置詞,也可以為特定的Action做出自訂的路由,例如:

[Route("api/[controller]")]
public class OrderController : ControllerBase
{
    [HttpGet("~/orders/")]
    public IEnumerable<Order> Get()
    {
        ...
    }
}

如此就可以直接透過/orders 呼叫到這個Action

參考資料
ASP.NET Core 中的路由


上一篇
[Day09]使用Swagger自動建立清晰明瞭的REST API文件 - 我與 ASP.NET Core 的 30天
下一篇
[Day11] URL重寫與URL重新導向 - 我與 ASP.NET Core 3 的 30天
系列文
我與 ASP.NET Core 的 30天31

尚未有邦友留言

立即登入留言