我已经使用 Web API 编写了一个 REST 服务,在阅读了 Brian Mulloy 的这个Web API 设计的部分之后,我试图弄清楚如何实现与 Web API 的关联。
Web API 设计摘录:
协会
资源几乎总是与其他资源有关系。在 WebAPI 中表达这些关系的简单方法是什么?
让我们再看看我们在名词中建模的 API 是好的,动词是坏的——与我们的狗资源交互的 API。请记住,我们有两个基本 URL:/dogs 和 dogs/1234。
我们使用 HTTP 动词来操作资源和集合。我们的狗属于主人。要获取属于特定所有者的所有狗,或为该所有者创建新狗,请执行 GET 或 POST:
获取 /owners/5678/dogs
发布 /owners/5678/dogs现在,关系可能很复杂。主人与兽医有关系,与狗有关系,与食物有关系,等等。经常看到人们将这些链接在一起,使 URL 达到 5 或 6 级深度。请记住,一旦您拥有一个级别的主键,您通常不需要包含上述级别,因为您已经获得了您的特定对象。换句话说,你不应该需要太多比我们上面的 /resource/identifier/resource 更深的 URL 的情况。
所以我尝试为关联添加一个控制器方法,如下所示:
public class EventsController : ApiController
{
// GET api/events
public IEnumerable<Event> Get()
{
// get list code
}
// GET api/events/5
public Event Get(int id)
{
// get code
}
// POST api/events
public void Post([FromBody]Event evnt)
{
// add code
}
// POST api/events/5
public void Post(int id, [FromBody]Event evnt)
{
// update code
}
// DELETE api/events/5
public void Delete(int id)
{
// delete code
}
// GET api/events/5/guests
public IEnumerable<Guest> Guests(int id)
{
// association code
}
}
我还将路线模板修改为以下内容:
config.Routes.MapHttpRoute("ApiWithAssociations",
"api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
不幸的是,当我更新/发布事件资源时,我现在得到一个 HTTP 500 内部服务器错误,响应正文说明
找到多个与请求匹配的操作
我已经尝试修改路由模板以及添加 System.Web.Http.HttpPostAttribute (和其他 HTTP 动词),但无济于事。
有没有人试过这个并让它工作?任何帮助,将不胜感激。如果绝对不可能有多个 http 动词,那么我想我将不得不放弃与我的 REST 服务的关联。
编辑:解决方案
使用 Radim Köhler 的回答,我能够得到这个工作。将 HttpGetAttribute 添加到 Guest 方法中,如下所示:
// GET api/event/5/guests
[HttpGet]
public IEnumerable<Guest> Guests(int id)
{
// association code
}
并添加了一条附加路由来满足默认的 GET 操作,如下所示:
config.Routes.MapHttpRoute("DefaultGet",
"api/{controller}/{id}",
new {action = "Get"},
new {httpMethod = new HttpMethodConstraint(HttpMethod.Get)});
config.Routes.MapHttpRoute("ApiWithAssociations",
"api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
"api/{controller}/{id}",
new {id = RouteParameter.Optional});