Ted Nyberg
Ted Nyberg

Reputation: 7391

ASP.NET Web API controller with attribute routing doesn't work without a route name

I use attribute routing, but when I specify an empty Route attribute I get the following error:

405.0 - Method Not Allowed

However, if I add a route name in the attribute, like [Route("bar")], everything works as expected.

Why would one of these action methods work as expected, while the other one yields a 405 error?

[System.Web.Http.RoutePrefix("foo")]
public partial class MyController : ApiController
{
   [System.Web.Http.HttpPost]
   [System.Web.Http.Route("bar")] // I am able to POST to /foo/bar
   public async Task<MyResponseModel> BarMethod([FromBody]MyArgumentsModel arguments)
   {

   }

   [System.Web.Http.HttpPost]
   [System.Web.Http.Route] // Error when I POST to /foo, "Method Not Allowed"
   public async Task<MyResponseModel> FooMethod([FromBody]MyArgumentsModel arguments)
   {

   }
}

Any ideas what I could be missing?

Upvotes: 4

Views: 5090

Answers (2)

Nkosi
Nkosi

Reputation: 246998

You need to include an empty string to the route attribute [Route("")] in order for it to work as the default route when using the route prefix.

The following article shows how it is done

Source: Attribute Routing in ASP.NET Web API 2

The result of the suggested change would look like this

[RoutePrefix("foo")]
public partial class MyController : ApiController {
   //eg POST foo/bar
   [HttpPost]
   [Route("bar")]
   public async Task<MyResponseModel> BarMethod([FromBody]MyArgumentsModel arguments) {
      //...
   }

   //eg POST foo    
   [HttpPost]
   [Route("")]
   public async Task<MyResponseModel> FooMethod([FromBody]MyArgumentsModel arguments) {
       //...
   }
}

Upvotes: 2

giammin
giammin

Reputation: 18958

Attribute routing can be combined with convention-based routing. To define convention-based routes, call the MapHttpRoute method.

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 } );
    }
}

Upvotes: 1

Related Questions