I have spent some considerable time trying to get Web API attribute routing working, and all I am getting are 404 errors no matter what I try.
I have a simple ApiController that tries to define a HttpGet at api/hello/{number}
and hello/{number}
:
public class HelloController : ApiController
{
public class Hello
{
public string user { get; set; }
public string password { get; set; }
}
[Route("api/hello/{number}")]
[Route("hello/{number}")]
[HttpGet]
public IEnumerable<Hello> GetStuff(int number)
{
var response = Request.CreateResponse(HttpStatusCode.Created, number);
return null;
}
[Route("api/hello")]
[HttpPost]
public HttpResponseMessage PostHello(Hello value)
{
var response = Request.CreateResponse(HttpStatusCode.Created, value);
return response;
}
}
I have this as my RouteConfig, enabling attribute routing:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
WebAPIConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
}
}
Finally, here is my Application_Start() where I register the WebApiConfig:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Does anyone see something I am missing? I get 404 errors (unable to hit a breakpoint in GetStuff()) for all of the following:
http://localhost/api/hello
http://localhost/api/hello/1
http://localhost/hello
http://localhost/hello/2
My post does not work either.
Your MVC routes are taking precedence over your API routes. Because you are using a catch all route for the MVC side ("{controller}/{action}/{id}"
), and it is being registered first, your routing will always look for an mvc controller named api
or hello
, because that's the route it matched.
Try moving your api registration above your MVC route registration in your Global.asax:
GlobalConfiguration.Configure(WebApiConfig.Register);
//then
RouteConfig.RegisterRoutes(RouteTable.Routes);