Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attribute based webapi2 routing returns 404 for some methods

I'm presently working on a project that has been upgraded to Webapi2 from Webapi. Part of the conversion includes the switch to using attribute based routing.

I've appropriately setup my routes in the Global.asax (as follows)

 GlobalConfiguration.Configure(config => config.MapHttpAttributeRoutes());

and removed the previous routing configuration.

I have decorated all of my API controllers with the appropriate System.Web.Http.RouteAttribute and System.Web.Http.RoutePrefixAttribute attributes.

If I inspect System.Web.Http.GlobalConfiguration.Configuration.Routes with the debugger I can see that all my expected routes are registered in the collection. Likewise the appropriate routes are available within the included generated Webapi Help Page documentation as expected.

Even though all appears to be setup properly a good number of my REST calls result in a 404 not found response from the server.

I've found some notable similarities specific to GET methods (this is all I've tested so far)

  • If a method accepts 0 parameters it will fail
  • If a route overrides the prefix it will fail
  • If a method takes a string parameter it is likely to succeed
  • return type seems to have no affect
  • Naming a route seems to have no affect
  • Ordering a route seems to have no affect
  • Renaming the underlying method seems to have no affect

Worth noting is that my API controllers appear in a separate area, but given that some routes do work I don't expect this to be the issue at hand.

Example of non-functional method call

[RoutePrefix("api/postman")]
public class PostmanApiController : ApiController
{
    ...
    [HttpGet]
    [Route("all", Name = "GetPostmanCollection")]
    [ResponseType(typeof (PostmanCollectionGet))]
    public IHttpActionResult GetPostmanCollection()
    {
        return Ok(...);
    }
    ...
}

I expect this to be available via http://[application-root]/api/postman/all

Interestingly enough a call to

Url.Link("GetPostmanCollection", null)

will return the above expected url

A very similar example of method calls within the same controller where some work and some do not.

[RoutePrefix("api/machine")]
public class MachineApiController : ApiController
{
    ...
    [HttpGet]
    [Route("byowner/{owner}", Name = "GetPostmanCollection")]
    public IEnumerable<string> GetByOwner([FromUri] string owner)
    {
        ...
    }
    ...

    [HttpGet]
    [Route("~/api/oses/{osType}")]
    public IEnumerable<OsAndVersionGet> GetOSes([FromUri] string osType)
    {
        ...
    }
    ...
}

Where a call to http://[application-root]/api/machineby/ownername succeeds and http://[application-root]/api/oses/osType does not.

I've been poking at this far too long, any idea as to what the issue may be?

like image 514
rheone Avatar asked Apr 17 '14 23:04

rheone


2 Answers

Check that you configure your HttpConfiguration via the MapHttpAttributeRoutes method before any ASP.NET MVC routing registration.

In accordance to Microsoft's CodePlex entry on Attribute Routing in MVC and Web API the Design section states:

In most cases, MapHttpAttributeRoutes or MapMvcAttributeRoutes will be called first so that attribute routes are registered before the global routes (and therefore get a chance to supersede global routes). Requests to attribute routed controllers would also be filtered to only those that originated from an attribute route.

Therefore, within the Global.asax (or where registering routes) it is appropriate to call:

GlobalConfiguration.Configure(c => c.MapHttpAttributeRoutes()); // http routes
RouteTable.Routes.MapRoute(...); // mvc routes
like image 64
mt_serg Avatar answered Nov 09 '22 05:11

mt_serg


In my case it was a stupid mistake, I am posting this so people behind me making the same mistake may read this before they check everything else at quantum level.

My mistake was, my controller's name did not end with the word Controller.

Happy new year

like image 31
fahadash Avatar answered Nov 09 '22 07:11

fahadash