How to map WebAPI routes correctly
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 routesconfig.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){...}}
Routing is order sensitive. The first match always wins. So it is important that you order you routes from most-specific to least-specific.
// All parameters are required, or it won't match.// So it will only match URLs 4 segments in length// starting with /api.config.Routes.MapHttpRoute( "1", "api/{controller}/{id}/{action}");// Controller is required, id is optional.// So it will match any URL starting with// /api that is 2 or 3 segments in length.config.Routes.MapHttpRoute( "2", "api/{controller}/{id}", new { action = "get", id = RouteParameter.Optional });
When your routes are ordered this way, you will get the behavior you expect.
There are a variety of useful reference materials on this subject, such as:
Have you had a look at these?
Update..
Its better practise to explicitly state which parameter is which, ie:
config.Routes.MapHttpRoute( name: "2", routeTemplate: "api/{controller}/{id}", defaults: new { action = "Get", id = RouteParameter.Optional }, ); config.Routes.MapHttpRoute( name: "1", routeTemplate: "api/{controller}/{action}/{id}", defaults: null );
Main thing I could see wrong was you had action / id in the wrong order in route "1".