Search code examples
c#.netasp.net-web-apiasp.net-web-api2asp.net-web-api-routing

Configure webapi2 route to support different kind of GET requests (action/id)


I would like to be able to support those URLs:

// GET:  api/Users              returns a list (all)
// GET:  api/Users/5            returns the user with Id 5
// GET:  api/Users/Active       returns a list (only those not soft-deleted)
// POST: api/Users              creates a user

I have first tried to configure it this way:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

But then I could not support the api/Users/Active request

So I tried to configure it this way:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

But then I can not support the api/Users/5 request

Is it possible to support both?


Solution

  • Register multiple routes.

    You can also provide constraints, which restrict how a URI segment can match a placeholder:

    constraints: new { id = @"\d+" }   // Only matches if "id" is one or more digits.
    

    Example

    // GET:  api/Users              returns a list (all)
    // GET:  api/Users/5            returns the user with Id 5
    // POST: api/Users              creates a user
    config.Routes.MapHttpRoute(
        name: "Api",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new { id = @"\d+" }
    );
    
    // GET:  api/Users/Active       returns a list (only those not soft-deleted)
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
    

    Or enable attribute routing.

    public static class WebApiConfig {
        public static void Register(HttpConfiguration config) {
            // Attribute routing.
            config.MapHttpAttributeRoutes();
    
            // Convention-based routing.
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    

    Controller

    [RoutePrefix("api/users")]
    public class UsersController : ApiController {
        // GET:  api/Users              returns a list (all)
        [HttpGet]
        [Route("")] 
        public IHttpActionResult Get() { ... }
        // GET:  api/Users/5            returns the user with Id 5
        [HttpGet]
        [Route("{id:int}")] 
        public IHttpActionResult Get(int id) { ... }
        // GET:  api/Users/Active       returns a list (only those not soft-deleted)
        [HttpGet]
        [Route("Active")] 
        public IHttpActionResult Active() { ... }
        // POST: api/Users              creates a user
        [HttpPost]
        [Route("")] 
        public IHttpActionResult Post(User user) { ... }
    }