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 ファイルで定義されます。

Image of Solution Explorer where routes are defined.

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 とルートを照合し、コントローラーを選択し、呼び出すアクションを選択する方法が正確に説明されています。