ASP.NET Web API获取子列表(分层资源)

我有以下rest架构,我想使用ASP.NET Web Api实现:

http://mydomain/api/students http://mydomain/api/students/s123 http://mydomain/api/students/s123/classes http://mydomain/api/students/s123/classes/c456 

我使用ApiController和以下两种方法使前两个链接正常工作:

 public class StudentsController : ApiController { // GET api/students public IEnumerable GetStudents() { } // GET api/students/5 public IEnumerable GetStudent(string id) { } } 

在同一个控制器中,(或者我需要一个名为ClassesController的不同控制器?),我如何实现最后两个链接? 另外,“类”部分的路由是什么样的(如果需要)?

这是我的WebApiConfig(我想保持动态,而不是硬编码到/ classes的路径,如果可能的话:

 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // EDIT - I'm getting 404's when trying to use this context.Routes.MapHttpRoute( name: "JobsApi", routeTemplate: this.AreaName + "/Students/{id}/Classes/{classId}", defaults: new { classId = RouteParameter.Optional } ); 

编辑这是我新创建的ClassesController:

 public class ClassesController : ApiController { // GET api/classes public IEnumerable Get(string id) { return null; } } 

我在尝试访问此url时遇到404错误:

 http://mydomain/api/students/s123/classes 

通过这种良好的分层方法,您可以更多地关注内部路由。 有一个很好的示例应用程序采用分层资源结构: PingYourPackage 。 检查出。

注意:我有一篇关于此问题的博客文章解释了下面的问题,并为那些包含一些代码示例的人提供了解决方案。 您可以查看更多详细信息:

  • ASP.NET Web API中的分层资源结构

让我通过设置示例场景简要解释一下这里的问题。 对于这些类型的情况,这可能不是理想的方法,但很好地解决了这些问题。 假设您的数据库中有以下两个附属公司,用于装运公司:

  • 会员1(身份证号码:100)
  • 会员2(身份证号码:101)

然后假设这些附属公司附加了一些货物:

  • 会员1(关键:100)
    • 发货1(钥匙:100)
    • 装运2(钥匙:102)
    • 装运4(钥匙:104)
  • 会员2(重点:101)
    • 装运3(钥匙:103)
    • 装运5(钥匙:105)

最后,我们希望拥有以下资源结构:

 GET api/affiliates/{key}/shipments GET api/affiliates/{key}/shipments/{shipmentKey} POST api/affiliates/{key}/shipments PUT api/affiliates/{key}/shipments/{shipmentKey} DELETE api/affiliates/{key}/shipments/{shipmentKey} 

路由问题

@Ali已经解释过了,但我在这里采用了不同的方法。 假设我们正在针对/api/affiliates/105/shipments/102发送GET请求。 请注意,此处的会员密钥是105,不存在。 所以,我们希望尽快终止请求。 我们可以使用per-route消息处理程序来实现这一点。

授权问题

如果您具有某种类型的身份validation,您可能希望确保(在我们的场景中)经过身份validation的用户和请求的联盟资源相关。 例如,假设Affiliate1Affiliate角色下进行身份validation,并且您已注册AuthorizeAttribute以检查“Affiliate”角色授权。 在这种情况下,您将失败,因为这意味着Affiliate1可以访问以下资源: /api/affiliates/101/shipments属于Affiliate2的/api/affiliates/101/shipments 。 我们可以使用自定义AuthorizeAttribute消除此问题。

所有权问题

现在,以下URI应该为我提供正确的数据:

GET / api / affiliates / 100 /货运/ 102

但是,以下URI会发生什么:

GET / api / affiliates / 100 /货运/ 103

这应该为您提供“404 Not Found”HTTP响应,因为其ID为100的 联盟会员不拥有ID为103货件

ASP.NET中的路由可以表达这些更复杂的规则,但需要明确设置。 例如,在这种情况下,您必须定义2个路由:

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

你会有一个控制器:

 public class ClassesController { public TheClass Get(int studentId, int classId) { .... } } 

这可能不是理想的,但主要的选择。

我正在进行分层路由,由于Web API中的实现问题,这是不可能的,但是这个问题现在已经修复,所以我可能会再次开始研究它。