带关联的RESTful Web API。 可能吗?

问题描述 投票:4回答:2

我使用Web API编写了一个REST服务,在阅读了Brian Mulloy的Web API设计部分之后,我试图弄清楚如何实现与Web API的关联。

Web API设计提取:

协会

资源几乎总是与其他资源有关系。 在WebAPI中表达这些关系的简单方法是什么?

让我们再看看我们在名词中建模的API是好的,动词是坏的-theAPI与我们的狗资源相互作用。 请记住,我们有两个基本URL:/ dogs和dogs / 1234。

我们使用HTTP动词来操作资源和集合。 我们的狗属于所有者。 要获得属于特定所有者的所有狗,或为该所有者创建新狗,请执行GET或POST:

GET / Owner / 5678 /狗
邮寄/拥有者/ 5678 /狗

现在,关系可能很复杂。 业主与兽医有关系,兽医与狗有关系,与食物有关系,等等。 通常会看到人们将这些字符串组合在一起,形成5或6级的URL。 请记住,一旦拥有一个级别的主键,通常不需要包含上面的级别,因为您已经拥有了特定的对象。 换句话说,您不应该需要太多的情况,其中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});
rest asp.net-web-api asp.net-web-api-routing
2个回答
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
投票
© www.soinside.com 2019 - 2024. All rights reserved.