I can't figure out why a route is being processed by MVC instead of Web API.
The whole route is configured as follows:
configuration.Routes.MapHttpRoute
(
name: "AdminControllers.TicketingController",
routeTemplate: "api/company/tickets",
defaults: new
{
controller = "Ticketing",
id = RouteParameter.Optional,
action = "GetTickets"
}
);
And the API controller looks like this:
public sealed class TicketingController : ApiController
{
[HttpGet]
public HttpResponseMessage GetTickets()
{
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK);
}
}
I perform a HTTP/GET request to /api/company/tickets
and I get the following error:
The controller for path "/api/company/tickets" was not found or does not implement IController.
Exception's stack trace points to ASP.NET MVC (not Web API): System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
.
AFAIK, this happens when you map a route using the wrong framework (MVC) instead of Web API HttpConfiguration.Routes.MapHttpRoute
extension method. In my sample found above you'll find I'm using the right resource to register a controller in Web API.
I can confirm that the route gets registered during application startup.
The problem is ASP.NET MVC pipeline handles the route and, obviously, it does find no controller for the whole route.
What am I doing wrong here?
NOTE: It's ASP.NET Web API 1.x and I can't use Web API 2.0 (I would love to use attribute routing, yeah).
Update: A pic of registered routes after invoking .MapHttpRoute(...)
Update 2
Believe or not, but it started to work when I changed route configuration to:
configuration.Routes.MapHttpRoute(
name: "AdminControllers.TicketingController",
routeTemplate: "api/company/tickets/{id}",
defaults: new
{
controller = "Ticketing",
id = RouteParameter.Optional,
action = "GetTickets"
}
);
And Web API action changed to:
[HttpGet]
public HttpResponseMessage GetTickets(int? id)
{
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK);
}
It seems like a route parameter makes the route different enough to be ignored by MVC and then processed by Web API pipeline. But I can confirm that there's no other route starting with "api/company/".
Anyway, it works if I give the id
(f.e. /api/company/tickets/11
). Otherwise, MVC pipeline processes the route...
After looking for solutions, I've got a working one.
First of all, I'm deploying a Web API controller to Windows Azure Pack administrator's site (AdminSite). It's made with ASP.NET MVC 4.0. Anyway, I believe my answer should make sense if you find the same problem I'm going to describe in any ASP.NET MVC and Web API mixed application.
Windows Azure Pack registers this ASP.NET MVC route:
{controller}/{action}/{id}
: PROBLEM!*Yes, because it's an URL route that can fit in Web API controller URI scheme...**
So... what?
At the end of the day, this is solved putting Web API routes before MVC ones. This way, ASP.NET will route requests to the first coincidence of some URI route pattern:
Wait, Web API routes are registered into
GlobalConfiguration.Configuration.Routes
route table...Yes, but
HttpConfiguration.Routes
registers its routes inRouteTable.Routes
too, and ASP.NET pipeline works withRouteTable.Routes
. That is, both MVC and WebAPI routes are in the same route table.In the following screenshot, you'll find that Web API routes are of type
HttpWebRoute
:Now these URIs are served by the fancy Web API controller:
An extension method to make our life even easier!
After I checked that this solution was working, I refactored above sample code to an extension method:
...and now I'm able to add routes at the top of routing table as follows: