ASP.NET Web API 中的路由

本文說明 ASP.NET Web API如何將 HTTP 要求路由傳送至控制器。

注意

如果您熟悉 ASP.NET MVC,Web API 路由與 MVC 路由非常類似。 主要差異在於 Web API 會使用 HTTP 動詞命令,而不是 URI 路徑來選取動作。 您也可以在 Web API 中使用 MVC 樣式路由。 本文不會假設 ASP.NET MVC 的任何知識。

路由表

在 ASP.NET Web API中,控制器是處理 HTTP 要求的類別。 控制器的公用方法稱為 動作方法 ,或只是 動作。 當 Web API 架構收到要求時,它會將要求路由傳送至動作。

若要判斷要叫用的動作,架構會使用 路由表。 Web API 的 Visual Studio 專案範本會建立預設路由:

routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

此路由定義于 WebApiConfig.cs 檔案中,該檔案會放在 App_Start 目錄中:

定義路由方案總管影像。

如需 類別 WebApiConfig 的詳細資訊,請參閱設定 ASP.NET Web API

如果您自我裝載 Web API,則必須直接在 物件上 HttpSelfHostConfiguration 設定路由表。 如需詳細資訊,請參閱 自我裝載 Web API

路由表中的每個專案都包含 路由範本。 Web API 的預設路由範本為 「api/{controller}/{id}」。 在此範本中,「api」 是常值路徑區段,而 {controller} 和 {id} 是預留位置變數。

當 Web API 架構收到 HTTP 要求時,它會嘗試比對路由表中其中一個路由範本的 URI。 如果沒有相符的路由,用戶端會收到 404 錯誤。 例如,下列 URI 符合預設路由:

  • /api/contacts
  • /api/contacts/1
  • /api/products/gizmo1

不過,下列 URI 不相符,因為它缺少 「api」 區段:

  • /contacts/1

注意

在路由中使用 「api」 的原因是避免與 ASP.NET MVC 路由發生衝突。 如此一來,您可以讓 「/contacts」 移至 MVC 控制器,而 「/api/contacts」 則移至 Web API 控制器。 當然,如果您不喜歡此慣例,您可以變更預設路由表。

找到相符的路由之後,Web API 會選取控制器和動作:

  • 若要尋找控制器,Web API 會將 「Controller」 新增至 {controller} 變數的值。
  • 若要尋找動作,Web API 會查看 HTTP 動詞,然後尋找名稱以該 HTTP 動詞名稱開頭的動作。 例如,使用 GET 要求時,Web API 會尋找前面加上 「Get」 的動作,例如 「GetContact」 或 「GetAllContacts」。 此慣例僅適用于 GET、POST、PUT、DELETE、HEAD、OPTIONS 和 PATCH 動詞命令。 您可以在控制器上使用屬性來啟用其他 HTTP 動詞。 我們稍後會看到該範例。
  • 路由範本中的其他預留位置變數,例如 {id}, 會對應至動作參數。

讓我們看看下列範例。 假設您定義下列控制器:

public class ProductsController : ApiController
{
    public IEnumerable<Product> GetAllProducts() { }
    public Product GetProductById(int id) { }
    public HttpResponseMessage DeleteProduct(int id){ }
}

以下是一些可能的 HTTP 要求,以及針對每個要求叫用的動作:

HTTP 指令動詞 URI 路徑 動作 參數
GET api/products GetAllProducts (無)
GET api/products/4 GetProductById 4
刪除 api/products/4 DeleteProduct 4
POST api/products (不相符)

請注意,如果存在,URI 的 {id} 區段會對應至動作的 id 參數。 在此範例中,控制器會定義兩個 GET 方法,一個具有 id 參數,另一個沒有參數。

另請注意,POST 要求將會失敗,因為控制器不會定義 「Post...」 方法。

路由變化

上一節說明 ASP.NET Web API的基本路由機制。 本節說明一些變化。

HTTP 動詞

您可以藉由使用下列其中一個屬性來裝飾動作方法,以明確指定動作的 HTTP 動詞,而不是使用 HTTP 動詞的命名慣例:

  • [HttpGet]
  • [HttpPut]
  • [HttpPost]
  • [HttpDelete]
  • [HttpHead]
  • [HttpOptions]
  • [HttpPatch]

在下列範例中 FindProduct ,方法會對應至 GET 要求:

public class ProductsController : ApiController
{
    [HttpGet]
    public Product FindProduct(id) {}
}

若要允許動作的多個 HTTP 動詞,或允許 GET、PUT、POST、DELETE、HEAD、OPTIONS 和 PATCH 以外的 HTTP 動詞命令,請使用 [AcceptVerbs] 屬性,其會採用 HTTP 動詞清單。

public class ProductsController : ApiController
{
    [AcceptVerbs("GET", "HEAD")]
    public Product FindProduct(id) { }

    // WebDAV method
    [AcceptVerbs("MKCOL")]
    public void MakeCollection() { }
}

依動作名稱路由

使用預設路由範本時,Web API 會使用 HTTP 動詞命令來選取動作。 不過,您也可以建立路由,其中動作名稱包含在 URI 中:

routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

在此路由範本中, {action} 參數會將控制器上的動作方法命名為 。 使用此路由樣式時,請使用屬性來指定允許的 HTTP 動詞命令。 例如,假設您的控制器具有下列方法:

public class ProductsController : ApiController
{
    [HttpGet]
    public string Details(int id);
}

在此情況下,「api/products/details/1」 的 GET 要求會對應至 Details 方法。 此路由樣式類似于 ASP.NET MVC,而且可能適用于 RPC 樣式 API。

您可以使用 屬性覆寫動作名稱 [ActionName] 。 在下列範例中,有兩個動作對應至 「api/products/thumbnail/id。其中一個支援 GET,另一個則支援 POST:

public class ProductsController : ApiController
{
    [HttpGet]
    [ActionName("Thumbnail")]
    public HttpResponseMessage GetThumbnailImage(int id);

    [HttpPost]
    [ActionName("Thumbnail")]
    public void AddThumbnailImage(int id);
}

非動作

若要防止方法叫用為動作,請使用 [NonAction] 屬性。 這會向架構發出訊號,指出方法不是動作,即使它與其他路由規則相符也一樣。

// Not an action method.
[NonAction]  
public string GetPrivateData() { ... }

深入閱讀

本主題提供路由的高階檢視。 如需詳細資料,請參閱 路由和動作選取,其中描述架構如何完全符合 URI 與路由、選取控制器,然後選取要叫用的動作。