2012-11-28 11 views
84

IはGlobal.asaxの中にデフォルトルートを有する:ウェブAPIルーティング - API/{コントローラ}/{アクション}/{ID} "機能不全" API/{コントローラ}/{ID}

RouteTable.Routes.MapHttpRoute(
     name: "DefaultApi", 
     routeTemplate: "api/{controller}/{id}", 
     defaults: new { id = System.Web.Http.RouteParameter.Optional } 
     ); 

Iを特定の機能をターゲットできるようにしたかったので、私は別のルートを作成しました:

RouteTable.Routes.MapHttpRoute(
     name: "WithActionApi", 
     routeTemplate: "api/{controller}/{action}/{id}", 
     defaults: new { id = System.Web.Http.RouteParameter.Optional } 
     ); 

だから、私のコントローラでは、私が持っている:

public string Get(int id) 
    { 
     return "object of id id"; 
    }   

    [HttpGet] 
    public IEnumerable<string> ByCategoryId(int id) 
    { 
     return new string[] { "byCategory1", "byCategory2" }; 
    } 

の呼び出しを私が欲しいものを私に与えるでしょう。しかし 、.../api/records/1はエラー

複数のアクションが要求に一致することが判明し、私を与えるだろう呼び出す:つまり、なぜ私が理解

... - ルートはちょうどURLが有効であるかを定義しますが、ファンクションマッチングになると、Get(int id)ByCategoryId(int id)api/{controller}/{id}と一致します。これはというフレームワークを混乱させます。

デフォルトのAPIルートを再度使用するには、何をする必要がありますか?{action}のままにしておきますか?私はRecordByCategoryIdControllerという別のコントローラを作成してデフォルトのAPIルートに一致させることを考えましたが、そのためには.../api/recordbycategoryid/5をリクエストします。しかし、私はそれが "汚い"(したがって不満足な)解決策であることがわかります。私はこれについての答えを探しましたが、{action}のルートを使ってこの問題について言及しているチュートリアルはありません。

答えて

95

ルートエンジンはルールを追加するのと同じシーケンスを使用します。最初に一致したルールを取得すると、他のルールのチェックを停止し、これを使用してコントローラとアクションを検索します。

だから、あなたがすべき:

  1. が先にあなたの一般的な規則の特定のルールを入れて(デフォルトのように)、これは、最初の「WithActionApi」、そして「DefaultApi」をマッピングするためにRouteTable.Routes.MapHttpRouteを使用することを意味します。

  2. 「WithActionApi」ルールのパラメータを削除すると、idがオプションであるため、「/ api/{part1}/{part2}」のURLは「DefaultApi」には決して入れられないためです。

  3. "DefaultApi"に名前付きアクションを追加して、ルートエンジンにどのアクションを入力するかを指示します。それ以外の場合は、コントローラに複数のアクションがあると、エンジンはどちらを使用するかを知らず、 "要求に一致する複数のアクションが見つかりました:..."をスローします。 Getメソッドに一致させるには、ActionNameAttributeを使用します。

    // Map this rule first 
    RouteTable.Routes.MapRoute(
        "WithActionApi", 
        "api/{controller}/{action}/{id}" 
    ); 
    
    RouteTable.Routes.MapRoute(
        "DefaultApi", 
        "api/{controller}/{id}", 
        new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional } 
    ); 
    

    そして、あなたのコントローラ:

だからあなたのルートは次のようにする必要があり

[ActionName("DefaultAction")] //Map Action and you can name your method with any text 
public string Get(int id) 
{ 
    return "object of id id"; 
}   

[HttpGet] 
public IEnumerable<string> ByCategoryId(int id) 
{ 
    return new string[] { "byCategory1", "byCategory2" }; 
} 
+1

私は上記のアドバイスを試しましたが、すべてが期待通りに機能します。その "秘密"をありがとうございました。 –

+0

あなたの答えの2番目の点で、 'id'がオプションの場合、' WithActionApi'ルートに一致するアクションが見つからなければ '/ api/{part1}/{part2}'のようなURLは 'DefaultApi'ルートに入ります。私が間違っているなら、私を修正してください。 – orad

33

をあなたは

コントローラをルーティング属性の助けを借りて、あなたの問題を解決することができます jqueryの中

[Route("api/category/{categoryId}")] 
public IEnumerable<Order> GetCategoryId(int categoryId) { ... } 

URI

api/category/1 

ルート設定

using System.Web.Http; 

namespace WebApplication 
{ 
    public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API routes 
      config.MapHttpAttributeRoutes(); 

      // Other Web API configuration not shown. 
     } 
    } 
} 

とデフォルトのルーティングはデフォルト規則ベースのルーティング

として働いています

コントローラ

public string Get(int id) 
    { 
     return "object of id id"; 
    } 

URIのjQuery

/api/records/1 

ルート設定

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Attribute routing. 
     config.MapHttpAttributeRoutes(); 

     // Convention-based routing. 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 
    } 
} 

詳しくAttribute routing and onvention-based routing hereのレビュー記事this

+0

神の答え。 api/{controller}/{id}と一緒にapi/{controller}/{action}/{id}を追加することはできませんか? – karim

+0

属性ルーティングは、問題を確実に解決します。重要なポイントの1つ:Web API 2より前のWeb APIプロジェクトテンプレートでは、次のようなコードが生成されました。 protected void Application_Start() {WebApiConfig.Register(GlobalConfiguration.Configuration); }属性ルーティングが有効な場合、このコードは例外をスローします。既存のWeb APIプロジェクトをアップグレードして属性ルーティングを使用する場合は、この構成コードを次のように更新してください。 protected void Application_Start() {GlobalConfiguration.Configure(WebApiConfig.Register); } – Deeb

関連する問題