共用方式為


ASP.NET Web API 中的路由

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

注意

如果您熟悉 MVC ASP.NET,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 類別的詳細資訊,請參閱設定 web API ASP.NET

如果您自我裝載 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
DELETE 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、選取控制器,然後選取要叫用的動作。