iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Software Development

使用 C# 從零開始玩轉 Web API,從基礎到微服務與雲端部署的全面探索系列 第 14

Day 14 .Net Core Web API 實做 (下) 控制器與路由設定

  • 分享至 

  • xImage
  •  

在 .NET Core Web API 中,控制器路由是實現 API 請求的核心組件。控制器負責處理 HTTP 請求並生成對應的回應,而路由則決定每個請求應該被哪個控制器處理。本篇文章將深入探討如何在 .NET Core Web API 中配置控制器路由,以及設計路由時應該考慮的重點。


控制器與路由的基本概念

  1. 控制器(Controller)
    控制器是處理 HTTP 請求的核心單元。在 ASP.NET Core 中,每個控制器都包含一個或多個動作方法(Action Methods),這些方法負責處理特定的請求。通常,控制器名稱以 Controller 作為結尾,例如 ProductControllerOrderController
  2. 路由(Routing)
    路由的任務是將傳入的 HTTP 請求映射到控制器的某個動作方法。透過路由,Web API 可以根據請求的 URL 與 HTTP 方法(GET、POST、PUT、DELETE 等)來決定對應的控制器和方法。

路由的配置方式

在 .NET Core Web API 中,路由通常有兩種設定方式:

  1. 傳統路由(Convention-Based Routing)
  2. 屬性路由(Attribute Routing)

1. 傳統路由(Convention-Based Routing)

ASP.NET Core Web API 中,傳統的路由模式也可以透過 Startup.cs 來進行配置。這種方式一般適用於簡單的專案,或是對於不需要非常自定義路徑的場景。

範例:傳統路由設定

Startup.csConfigure 方法中,我們可以設置一個簡單的預設路由:

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

在這裡,我們定義了預設的路由規則:

  • {controller=Home}:預設控制器為 HomeController
  • {action=Index}:預設動作為 Index
  • {id?}id 是可選參數。

這種配置方式雖然簡單,但靈活性不如屬性路由,特別是在 API 設計中,屬性路由能更直觀地表現出 API 的資源路徑和操作。

2. 屬性路由(Attribute Routing)

屬性路由是透過將路由資訊直接標註在控制器與動作方法上來進行設定的。它提供了非常靈活且可讀性高的方式來設定路由。屬性路由適合 API 服務,因為 API 路徑往往需要明確且可控。

範例:基本屬性路由設定

[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    // GET api/product
    [HttpGet]
    public IEnumerable<Product> GetProducts()
    {
        // 取得所有產品
    }

    // GET api/product/{id}
    [HttpGet("{id}")]
    public ActionResult<Product> GetProductById(int id)
    {
        // 依據 ID 取得特定產品
    }

    // POST api/product
    [HttpPost]
    public ActionResult CreateProduct(Product product)
    {
        // 新增一個產品
    }
}

在這個範例中,[Route("api/[controller]")] 會將所有請求 /api/product 映射到 ProductController[controller] 是一個佔位符,會自動匹配控制器名稱(去掉 "Controller" 後綴)。

  • [HttpGet]:處理 GET 請求,api/product 對應 GetProducts 方法。
  • [HttpGet("{id}")]:處理帶有 id 參數的 GET 請求,路徑會是 api/product/{id},對應 GetProductById 方法。
  • [HttpPost]:處理 POST 請求,路徑為 api/product,用來新增產品。

進階屬性路由設定

除了基本的路由配置,屬性路由允許我們更靈活地控制路徑與參數,以下是一些進階的設定範例:

[Route("api/[controller]")]
[ApiController]
public class OrderController : ControllerBase
{
    // GET api/order/{orderId}/items
    [HttpGet("{orderId}/items")]
    public ActionResult<IEnumerable<OrderItem>> GetOrderItems(int orderId)
    {
        // 根據訂單 ID 取得所有訂單項目
    }

    // PUT api/order/{orderId}/item/{itemId}
    [HttpPut("{orderId}/item/{itemId}")]
    public ActionResult UpdateOrderItem(int orderId, int itemId, [FromBody] OrderItem updatedItem)
    {
        // 根據訂單 ID 與項目 ID 更新訂單項目
    }
}

這裡的路由變得更為具體:GET api/order/{orderId}/items 用於查詢訂單項目,而 PUT api/order/{orderId}/item/{itemId} 則用於更新特定訂單的特定項目。這種設計可以清楚地表示資源之間的層次結構。


路由設定時應注意的問題

  1. 路由的唯一性與可讀性

    每個路徑應該是唯一且可識別的。在設計 API 時,路徑應清楚地表達資源與操作。例如,針對產品資源的 API,可以這樣設計:

    • GET /api/products:獲取所有產品
    • GET /api/products/{id}:根據 ID 獲取特定產品
    • POST /api/products:新增產品
    • PUT /api/products/{id}:更新特定產品
    • DELETE /api/products/{id}:刪除特定產品

    這樣的路由設計簡潔且符合 RESTful API 標準。

  2. 版本控制

    當我們設計 API 時,版本控制是必須考慮的問題,特別是在需要長期維護和更新的系統中。可以通過路徑來進行版本控制,例如:

    [Route("api/v1/[controller]")]
    [ApiController]
    public class ProductController : ControllerBase
    {
        // v1 的 API
    }
    
    [Route("api/v2/[controller]")]
    [ApiController]
    public class ProductV2Controller : ControllerBase
    {
        // v2 的 API,可能改變了部分行為或返回結構
    }
    
    

    這樣的版本控制確保了 API 的向後兼容性,避免了新版本 API 改動導致舊版本的應用無法正常工作。

  3. 多個參數與路由模板

    當需要在 URL 中傳遞多個參數時,可以通過路由模板來靈活設計。例如,在訂單和訂單項目中,可以這樣設計:

    [HttpGet("order/{orderId}/item/{itemId}")]
    public ActionResult<OrderItem> GetOrderItem(int orderId, int itemId)
    {
        // 根據訂單 ID 和項目 ID 取得訂單項目
    }
    
    

    路徑 /order/{orderId}/item/{itemId} 清楚地表示了訂單與訂單項目之間的關聯。

  4. URL 可預測性

    設計 API 路徑時應保持一致性與可預測性,這樣開發者在使用 API 時能夠更容易理解。例如,對於不同的資源類型,應該遵循相似的路由模式,如 /api/orders/api/products,讓使用者能夠直觀預測資源路徑。


路由的最佳實踐

  1. 簡潔而有描述性
    路徑應該是簡潔且描述性的。例如,/api/products 清楚地表達了資源的性質(產品),避免使用過多的動詞,如 /api/getAllProducts
  2. 遵循 RESTful 標準
    路徑應遵循 RESTful API 的命名規則,資源用名詞表示,動作通過 HTTP 動詞來表達(如 GETPOSTPUTDELETE),避免將動作放入 URL 中。
  3. 考慮版本控制
    適當地加入版本控制機制,保證 API 的穩定性與向後兼容性。
  4. 參數的靈活使用
    利用路徑參數來表達資源的層次結構或關聯,讓 API 路徑更具語義性和結構化。

每日小結

在今天的文章中,我們深入探討了控制器與路由的設定,特別是屬性路由與傳統路由的配置方式。在設計 API 時,路由應該是簡潔、可讀、可預測並且遵循 RESTful 的原則。同時,我們還討論了路由設計時應該考慮的版本控制與參數管理。希望通過這篇文章,你能夠更好地設計清晰且有效的 API 路由。


上一篇
Day 13 .Net Core Web API 實做 (上)基礎專案建立
下一篇
Day 15 淺談開發與測試
系列文
使用 C# 從零開始玩轉 Web API,從基礎到微服務與雲端部署的全面探索22
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言