This is a random one, and it has me flummoxed.
I just updated my project to WebAPI 2 so I can make use of the new Attribute Routing feature. I followed the tutorial on the official site, and ended up with config in my global file like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Then in the WebApiConfig
class I'm setting up attribute routing like so:
public static void Register(HttpConfiguration config)
{
config.DependencyResolver = new DependencyResolverFactory();
config.MapHttpAttributeRoutes();
}
Then I want an action method with route "api/users/{id}":
[Route("api/users/{id}")]
public UserAccountModel GetUserAccount(string id)
{
return _userAccountService.GetAccountDetails(id);
}
This all looks good to me so far. However, when I try and hit this route I get an exception:
The IControllerFactory 'withoomph.Common.Ioc.DependencyControllerFactory' did not return a controller for the name 'api'.
The DependencyControllerFactory
is where I doing my dependency injection for my MVC controllers, so not sure why it is going there.
The strange thing is, if I change the route so it has an extra part to it:
[Route("api/users/test/{id}")]
public UserAccountModel GetUserAccount(string id)
{
return _userAccountService.GetAccountDetails(id);
}
It works! I have tried this out in a few different controllers, with different names, using api, not using api etc. And it is always the same: if the route has less than 4 parts to it, it doesn't work. Any more than 4, it works.
Does anyone know what he fudge is going on??!!
You need to re-order your registration code above as your request url is being matched by MVC routes as its more generic (ex: {controller}/{action}/{id}
) compared to Web API's specific route (api/{controller}/{id}
). As per routing guidelines, more specific routes must be registered before generic routes.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}