web-dev-qa-db-ja.com

ASP.NET Web APIで階層ルートを処理する方法は?

現在2つのコントローラーがあります

1-親コントローラー

2-子コントローラー

私はこのように私の親コントローラーにアクセスします

_someurl\parentcontroller
_

今、私はこのように私の子供のコントローラーにアクセスしたいです

_someurl\parentcontroller\1\childcontroller
_

この最後のURLは、特定の親のすべての子を返す必要があります。

現在、このルートはglobal.asaxファイルにあります

routes.MapHttpRoute ("Route1", "{controller}/{id}", new { id = RouteParameter.Optional });

_parent\id\child_階層をどのように達成できるかわかりません。これを実現するには、ルートをどのように構成すればよいですか?アイデア?

36
Haris Hasan

以下のようにルートを設定します。 {param}はオプションです(必要な場合に使用):

routes.MapHttpRoute(
           name: "childapi",
           routeTemplate: "api/Parent/{id}/Child/{param}",
           defaults: new { controller = "Child", param = RouteParameter.Optional }
  );

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

次に、子APiを/ api/Parent/1/childとして呼び出します。親は/ api/Parent /のように単純に呼び出すことができます。

子コントローラー:

    public class ChildController : ApiController
    {     
        public string Get(int id)
        {
          //the id is id between parent/{id}/child  
          return "value";
        }
        .......
    }
31
Abhijit_K

Web API 2以降、ルート属性を使用してメソッドごとにカスタムルーティングを定義できるようになりました。

[Route("api/customers/{id:guid}/orders")]
public IEnumerable<Order> GetCustomerOrders(Guid id) {
   return new Order[0];
}

また、次の行をWebApiConfig.Register()初期化メソッドに追加する必要があります。

  config.MapHttpAttributeRoutes();

記事全文 http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

18
Daniel Halan

私は、Abhijit Kadamが行ったように、ChildControllerをcontroller = "Child"に直接接続するのではなく、より一般的な方法でこれを処理したいと考えていました。私にはいくつかの子コントローラーがあり、controller = "ChildX"controller = "ChildY"を何度も使用して、それぞれに特定のルートをマップする必要はありませんでした。

私のWebApiConfigは次のようになります:

config.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);
  config.Routes.MapHttpRoute(
  name: "ChildApi",
  routeTemplate: "api/{parentController}/{parentId}/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);

私の親コントローラーは非常に標準的で、上記のデフォルトルートと一致しています。サンプルの子コントローラーは次のようになります。

public class CommentController : ApiController
{
    // GET api/product/5/comment
    public string Get(ParentController parentController, string parentId)
    {
        return "This is the comment controller with parent of "
        + parentId + ", which is a " + parentController.ToString();
    }
    // GET api/product/5/comment/122
    public string Get(ParentController parentController, string parentId,
        string id)
    {
        return "You are looking for comment " + id + " under parent "
            + parentId + ", which is a "
            + parentController.ToString();
    }
}
public enum ParentController
{
    Product
}

私の実装のいくつかの欠点

  • ご覧のとおり、私はenumを使用したため、2つの別々の場所で親コントローラーを管理する必要があります。それは文字列パラメーターと同じくらい簡単にできたかもしれませんが、api/crazy-non-existent-parent/5/comment/122が機能しないようにしたかったのです。
  • おそらく、リフレクションなどを使用して、個別に管理せずにその場でこれを実行する方法がありますが、今のところ、これでうまくいきます。
  • それは子供たちの子供たちをサポートしません。

おそらくもっと一般的なより良い解決策がありますが、私が言ったように、これは私にとってはうまくいきます。

10
mo.

デフォルトのmvcルーティングを使用する以外のオプションは、属性ルーティング- https://github.com/mccalltd/AttributeRouting を調べることです。より複雑ですが、個々のアクションメソッドを装飾することで、複雑なルートを設計する必要がある場合に多くの柔軟性が得られます。標準のMVCルーティングと組み合わせて使用​​することもできます。

5
AlexGad