I have an entity named Agency with following apis
GET     http://localhost:37331/api/agency?start=1&limit=10&status=1
GET     http://localhost:37331/api/agency/2
POST    http://localhost:37331/api/agency 
PUT     http://localhost:37331/api/agency
DELETE  http://localhost:37331/api/agency/4
POST    http://localhost:37331/api/agency/activate/3
POST    http://localhost:37331/api/agency/deactivate/3
GET     http://localhost:37331/api/agency/types
The route templates I used are
        config.Routes.MapHttpRoute(
            name: "ControllerActionIdApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { },
            constraints: new { id = @"\d+" }
        );
        //
        config.Routes.MapHttpRoute(
            name: "ControllerActionApi",
            routeTemplate: "api/{controller}/{action}"
        );
        //
        config.Routes.MapHttpRoute(
            name: "ControllerIdApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { },
            constraints: new { id = @"\d+" }
        );
        //
        config.Routes.MapHttpRoute(
            name: "ControllerApi",
            routeTemplate: "api/{controller}"
        );
Obviously there is ambiguous between the 2nd and 3rd. I do have a workaround that put the id into query string
GET     http://localhost:37331/api/agency?id=2
DELETE  http://localhost:37331/api/agency?id=4
I think there must be smart way. Could you please suggest on this?
Thanks
The routes are matched in sequence. Your constraint: new { id = @"\d+" } on the 3rd route isn't getting a look-in because the 2nd route will always win.
So swap your 2nd and 3rd routes around.
Always put the most selective routes at the top.
    config.Routes.MapHttpRoute(
        name: "ControllerActionIdApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { },
        constraints: new { id = @"\d+" }
    );
    //
    config.Routes.MapHttpRoute(
        name: "ControllerIdApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { },
        constraints: new { id = @"\d+" }
    );
    //
    config.Routes.MapHttpRoute(
        name: "ControllerActionApi",
        routeTemplate: "api/{controller}/{action}"
    );
    //
    config.Routes.MapHttpRoute(
        name: "ControllerApi",
        routeTemplate: "api/{controller}"
    );
Try this
routeTemplate: "api/{controller}/{action}/{id}"
来源:https://stackoverflow.com/questions/14638447/asp-net-web-api-route-templates