我使用Web API编写了一个REST服务,在阅读了Brian Mulloy的这个Web API Design部分之后,我试图弄清楚如何实现与Web API的关联。
Web API设计摘录:
关联
资源几乎总是与其他人有关系 资源。什么是表达这些关系的简单方法 aWebAPI?
让我们再看一下我们在名词中建模的API是好的, 动词是坏的-theAPI与我们的狗资源相互作用。 请记住,我们有两个基本URL:/ dogs和dogs / 1234。
我们正在使用HTTP 用于操作资源和集合的动词。我们的狗属于 拥有者。让所有的狗属于特定的所有者,或 为该主人创建一条新狗,进行GET或POST:
GET / owner / 5678 / dogs
POST / owner / 5678 / dogs现在,关系可以 复杂。业主与兽医有关系 与狗有关系,与食物有关系,等等。 看到人们将这些字符串组合在一起制作URL 5并不罕见 或6级深。请记住,一旦拥有主键 级别,您通常不需要包含上述级别,因为 你已经有了特定的对象。换句话说,你不应该 需要太多的情况,其中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服务的关联。
编辑:解决方案
使用RadimKöhler的回答,我能够使这个工作。将HttpGetAttribute添加到Guests方法,如下所示:
// 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});
答案 0 :(得分:2)
解决方案可能是一个明确的POST映射
只需添加新定义,该定义将用于events / 5 POST
// explicit Post() mapping
config.Routes.MapHttpRoute(
name: "DefaultPost",
routeTemplate: "api/{controller}/{id}",
defaults: new { action = "Post" }
, constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
);
// existing
config.Routes.MapHttpRoute("ApiWithAssociations",
"api/{controller}/{id}/{action}");
config.Routes.MapHttpRoute("DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
答案 1 :(得分:1)