ASP.NET Web API でのルーティング
この記事では、ASP.NET Web API が HTTP 要求をコントローラーにルーティングする方法について説明します。
Note
ASP.NET MVC に慣れている場合、Web API ルーティングは MVC ルーティングとよく似ています。 主な違いは、Web API がアクションの選択に URI パスではなく HTTP 動詞を使用することです。 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 }
);
このルートは、App_Start ディレクトリに配置される WebApiConfig.cs ファイルで定義されます。
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
Note
ルートで "api" を使用する理由は、ASP.NET MVC ルーティングとの競合を回避するためです。 こうすることで、"/contacts" を MVC コントローラーに移動させ、"/api/contacts" を Web API コントローラーに移動させることができます。 もちろん、この規則が気に入らない場合は、既定のルート テーブルを変更できます。
一致するルートが見つかると、Web API によってコントローラーとアクションが選択されます。
- コントローラーを見つけるために、Web API によって {controller} 変数の値に "Controller" が追加されます。
- アクションを見つけるために、Web API は HTTP 動詞を調べ、その HTTP 動詞名で始まる名前のアクションを探します。 たとえば、GET 要求では、Web API は、"GetContact" や "GetAllContacts" など、"Get" というプレフィックスが付いたアクションを検索します。 この規則は、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 |
投稿 | api/products | "(一致なし)" |
URI の {id} セグメントが存在する場合は、アクションの id パラメータにマップされることに注意してください。 この例では、コントローラーは 2 つの GET メソッドを定義しており、1 つは id パラメータを持ち、もう 1 つはパラメータを持ちません。
また、コントローラーは "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 動詞を許可したりするには、HTTP 動詞のリストを取得する [AcceptVerbs]
属性を使用します。
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 にマップされる 2 つのアクションがあります。1 つは GET をサポートし、もう 1 つは 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 とルートを照合し、コントローラーを選択し、呼び出すアクションを選択する方法が正確に説明されています。