如何在ASP.NET Web API中处理分层路由?

时间:2012-05-28 11:29:24

标签: c#-4.0 asp.net-mvc-4 asp.net-web-api restful-url

目前我有两个控制器

1 - 家长控制器

2 - 儿童控制器

我像这样访问我的父控制器

someurl\parentcontroller

现在我想要像我这样访问我的孩子控制器

someurl\parentcontroller\1\childcontroller

此最后一个网址应该返回特定父级的所有子级。

我目前在global.asax文件中有这条路线

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

我不确定如何实现我的parent\id\child层次结构..我应该如何配置我的路由来实现这一目标?想法?

4 个答案:

答案 0 :(得分:31)

配置路由如下。 {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";
        }
        .......
    }

答案 1 :(得分:18)

从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

答案 2 :(得分:10)

我希望以更一般的方式处理这个问题,而不是像Abhijit Kadam那样直接用controller = "Child"连接ChildController。我有几个子控制器,并且不想为每个控制器映射一个特定的路由,而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,因此我仍然需要在两个不同的位置管理父控制器。它可以很容易地成为字符串参数,但我想阻止api/crazy-non-existent-parent/5/comment/122工作。
  • 可能有一种方法可以使用反射或其他东西来动态地执行此操作而无需进行单独管理,但这对我来说现在很有用。
  • 它不支持儿童。

可能有一个更好的解决方案甚至更普遍,但就像我说的,这对我有用。

答案 3 :(得分:5)

除了使用默认mvc路由之外的一个选项是查看属性路由 - https://github.com/mccalltd/AttributeRouting。虽然它的工作量很大,但是当您需要设计复杂的路线时,装饰个人行动方法可以提供很大的灵活性。您也可以将它与标准MVC路由结合使用。