Search code examples
c#asp.net-web-apiasp.net-mvc-routingurl-routing

WebApi Routing: api/{controller}/{id} and api/{controller}/{action} at the same time


I have default webapi routing configuration:

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

I want to support following scenarios:

//api/mycontroller
public IQueryable<MyDTO> Get();

//api/mycontroller/{id} where id can be anything except "customaction1" and "customaction2"
public HttpResponseMessage Get(string id);

//api/mycontroller/customaction
[HttpPost]
public void CustomAction1([FromBody] string data);
[HttpPost]
public void CustomAction2([FromBody] string data);

I have tried to apply [Route("api/mycontroller/customaction1")] to the CustomAction1 method, and similar to CustomAction2 but getting:

Multiple actions were found that match the request: CustomAction1 on type MyProject.WebApiService.MyController CustomAction2 on type MyProject.WebApiService.MyController


Solution

  • Make sure that you configured attribute routing along with your default configuration

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

    If you want to do the same with out attribute routing then you will need to configure routes explicitly

    //This one constrains id to be an int
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { action="Get", id = RouteParameter.Optional },
        constraints : new { id = @"\d" }
    );
    //This one should catch the routes with actions included
    config.Routes.MapHttpRoute(
        name: "ActionRoutes",
        routeTemplate: "api/{controller}/{action}"
    );