Skip to content

ASP.NET Core Web API 入門心得 - 淺談 non-RESTful 的 Route 覆寫

TLDR

  • 透過繼承 BasicController 並設定 [Route("[controller]/[action]")],可統一管理 API 路由,減少重複設定。
  • Controller 層級的 [Route] 會直接覆寫 BasicController 的預設路由。
  • Action 層級的 [Route] 預設會與 Controller 的路由進行串接。
  • 若 Action 需要完全取代 Controller 的路由設定,需在 [Route] 字串開頭加上 /~ 前綴。
  • 若僅需修改 Action 的 URL 名稱,建議使用 [ActionName] 屬性。

在 non-RESTful 風格的 Web API 開發中,為了簡化維護,通常會透過繼承 BasicController 來統一路由定義。

統一路由設定

什麼情況下會遇到這個問題:當專案規範採用 Controller/Action 格式,且希望避免在每個 Controller 中重複撰寫路由屬性時。

透過定義抽象類別 BasicController,可以將路由規則集中管理:

csharp
[ApiController]
[Route("[controller]/[action]")]
public abstract class BasicController : ControllerBase {
}

public class TestRouteController : BasicController {
    // URL: /TestRoute/TestAction
    [HttpPost]
    public void TestAction() {
    }
}

路由覆寫與串接規則

什麼情況下會遇到這個問題:當現有 API 路徑與預設規則不符,需要針對特定 Controller 或 Action 進行路徑調整時。

在 ASP.NET Core 中,[Route] 的行為取決於其放置的位置以及是否包含特殊前綴:

  • Controller 覆寫:在 Controller 上使用 [Route] 會直接取代 BasicController 的設定。
  • Action 串接:若在 Action 上使用 [Route],預設會與 Controller 的路由進行串接,容易導致路徑過長。
  • 完全覆寫 (絕對路徑):在 Action 的 [Route] 字串開頭加上 /~,可忽略 Controller 的路由設定。

以下為不同情境的實作範例:

csharp
[ApiController]
[Route("[controller]/[action]")]
public abstract class BasicController : ControllerBase {
}

[Route("Override/[action]")]
public class TestRouteController : BasicController {
    // 情境:Controller 覆寫 Route,Action 不處理
    // URL:/Override/OverrideController
    [HttpPost]
    public void OverrideController() {
    }

    // 常見誤用情境:Controller 和 Action 都覆寫 Route,導致 Action 的 URL 是兩者 Route 的串接
    // URL:/Override/OverrideAction/Action/OverrideAction
    [HttpPost]
    [Route("Action/[action]")]
    public void OverrideAction() {
    }

    // 情境:Action 不想使用 Controller 設定的 Route,在 Route 最前面加上 "/"
    // URL:/Action/OnlyAction
    [HttpPost]
    [Route("/Action/[action]")]
    public void OnlyAction() {
    }

    // 情境:Action 不想使用 Controller 設定的 Route,在 Route 最前面加上 "~",效果同上
    // URL:/Action/OnlyAction2
    [HttpPost]
    [Route("~/Action/[action]")]
    public void OnlyAction2() {
    }

    // 情境:單純只想要修改 Action 名稱
    // URL:/Override/Rename
    [HttpPost]
    [ActionName("Rename")]
    public void RenameAction() {
    }
}

結論

針對 non-RESTful 架構,建議優先使用 BasicController 進行全域路由規範。若需針對個別 Action 調整路徑,應優先評估是否僅需修改名稱(使用 [ActionName]),若需完全變更路徑結構,則務必使用 /~ 前綴以避免不必要的路由串接。

異動歷程

    • 初版文件建立。