How to map WebAPI routes correctly

Donny picture Donny · Mar 29, 2016 · Viewed 58.1k times · Source

I'm building an API for a Twitter like site using Web API and have trouble with mapping the routes

I have the following actions for the User controller:

public User Get(string firstname, string lastname)
public User Get(Guid id)
public User Friends(Guid id)
public User Followers(Guid id)
public User Favorites(Guid id)

The desired routes and the generated documentation should be:

api/users?firstname={firstname}&lastname={lastname}
api/users/{id}
api/users/{id}/friends
api/users/{id}/followers
api/users/{id}/favorites

In WebApiConfig.cs I have:

config.Routes.MapHttpRoute(
    "2",
    "api/{controller}/{id}",
    new { action = "get", id = RouteParameter.Optional }
);


config.Routes.MapHttpRoute(
     "1",
     "api/{controller}/{id}/{action}"
);

How can I map WebAPI routes correctly?

Answer

Nkosi picture Nkosi · Mar 29, 2016

Given the flexibility you want you should take a look at

Attribute Routing in ASP.NET Web API 2

In WebApiConfig.cs enable attribute routing like

// Web API routes
config.MapHttpAttributeRoutes();

In UserController

Note given the names of actions Friends, Followers and Favorites they imply returning collections rather than single user

[RoutePrefix("api/users")]
public class UserController: ApiController {

    //eg: GET api/users?firstname={firstname}&lastname={lastname}
    [HttpGet]
    [Route("")]
    public User Get([FromUri]string firstname,[FromUri] string lastname) {...}

    //eg: GET api/users/{id}
    [HttpGet]
    [Route("{id:guid}")]
    public User Get(Guid id){...}

    //eg: GET api/users/{id}/friends
    [HttpGet]
    [Route("{id:guid}/friends")]
    public IEnumerable<User> Friends(Guid id){...}

    //eg: GET api/users/{id}/followers
    [HttpGet]
    [Route("{id:guid}/followers")]
    public IEnumerable<User> Followers(Guid id){...}

    //eg: GET api/users/{id}/favorites
    [HttpGet]
    [Route("{id:guid}/favorites")]
    public IEnumerable<User> Favorites(Guid id){...}
}