我有以下休息架构,我想使用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<Student> GetStudents() {
}
// GET api/students/5
public IEnumerable<Student> 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 }
);
EDIT 这是我新创建的ClassesController:
public class ClassesController : ApiController {
// GET api/classes
public IEnumerable<TheClass> Get(string id) {
return null;
}
}
尝试访问此网址时出现404错误:
http://mydomain/api/students/s123/classes
答案 0 :(得分:7)
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中的实现问题而无法实现的,但此问题现已修复,因此我可能会再次开始处理它。
答案 1 :(得分:7)
通过这种优秀的分层方法,您可以更多地关注内部路由。有一个很好的示例应用程序采用分层资源结构:PingYourPackage。检查一下。
注意:我有一篇关于此问题的博文,解释了以下问题,并为那些包含一些代码示例的人提供了解决方案。您可以 查看更多详情:
让我通过设置示例场景简要解释一下这里的问题。对于这些类型的情况,这可能不是理想的方法,但很好地解决了这些问题。假设您的数据库中有以下两个附属公司,用于装运公司:
然后假设这些附属公司附加了一些货物:
最后,我们希望拥有以下资源结构:
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}
/api/affiliates/105/shipments/102
发送GET请求。请注意,此处的联盟密钥为105,但不存在。所以,我们希望尽快终止请求。我们可以使用每个路由的消息处理程序来实现这一点。
如果您具有某种类型的身份验证,则需要确保(在我们的场景中)经过身份验证的用户和请求的关联企业资源相关。例如,假设 Affiliate1 在会员角色下进行了身份验证,并且您已注册AuthorizeAttribute
以检查“关联企业”角色授权。在这种情况下,您将失败,因为这意味着 Affiliate1 可以访问以下资源:属于Affiliate2的/api/affiliates/101/shipments
。我们可以使用自定义AuthorizeAttribute
消除此问题。
现在,以下URI应该为我提供正确的数据:
GET / api / affiliates / 100 / shipment / 102
但是,以下URI会发生什么:
GET / api / affiliates / 100 / shipment / 103
这会让您获得“404 Not Found”HTTP响应,因为 100 的联属会员不拥有货件,其ID为的 103 强>