WebAPI - No action was found on the controller
Solution 1
This work around did thing for me:
config.Routes.MapHttpRoute(
name: "DefaultCAApi",
routeTemplate: "api/v1/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "LevelOneNested",
routeTemplate: "api/v1/{controller}/{id}/details/{action}",
defaults: new { id = RouteParameter.Optional }
);
Basically I have added 1 more path level to my url. It finally became:
/api/v1/actor/4/details/movies
Solution 2
Try switching the order of your routes:
config.Routes.MapHttpRoute(
name: "DefaultOneLevelNested",
routeTemplate: "api/v1/{controller}/{levelOneId}/{action}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultCAApi",
routeTemplate: "api/v1/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Order matters when creating routes. The way you have it, it's matching the first one (the default route) first, and not finding an action with the name of "1".
You might also want to look into MVC Attribute routing, I think it's a tad easier to work with: http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
Arry
An eternal student of Computer Science. Senior Data Engineer @ Intuit
Updated on June 28, 2022Comments
-
Arry almost 2 years
I am trying to make hierarchical link in my RESTapi. For example:
Following url will give me details of actor id 1:
/api/v1/actor/id/1/
Following url is expected to give me all movies of actor id 1:
/api/v1/actor/1/movies
My routes:
config.Routes.MapHttpRoute( name: "DefaultCAApi", routeTemplate: "api/v1/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultOneLevelNested", routeTemplate: "api/v1/{controller}/{levelOneId}/{action}", defaults: new { id = RouteParameter.Optional } );
My Actions in
ActorController
:[HttpGet] public HttpResponseMessage Id(int id) { // logic return Request.CreateResponse(HttpStatusCode.OK, actor); } [HttpGet] public HttpResponseMessage Movies(int levelOneId) { // logic return Request.CreateResponse(HttpStatusCode.OK, movies); }
But this setup is not working for me.
/api/v1/actor/id/1/
gives me proper responseBut
/api/v1/actor/1/movies
is throwing following error:No action was found on the controller 'Actor' that matches the name '1'."
I did follow this thread, but it did not work for me.
Can some please suggest what wrong I am doing here? I am using MVC 4, WebAPI.
-
Arry over 8 yearsThanks for your answer @BFree . I already tried it, and it does not work. If I switch the order, the other route stops working. I mean this one /api/v1/actor/id/1/
-
BFree over 8 yearsAh, I misread your question. If you want to follow REST, you should have your route be:
/api/v1/actor/1
and then change yourId
action to just be calledGet
. That should work with the route configuration I laid out. -
Mihai Caracostea over 8 yearsThis is because both urls match both routes. See my comment on the question. I'll post it as an answer if it suits your needs.
-
Arry over 8 years@BFree: I did change Id to Get(int id), but it didn't work. Changing to just Get() will also not work as I need id, like this /api/v1/actor/1 Can you please explain your solution a bit?
-
Arry over 8 yearsThanks @Mihai for your answer. With your solution this worked: api/v1/actor/1/movies But /api/v1/actor/id/1/ is still giving error: No action was found on the controller
-
Mihai Caracostea over 8 years/api/v1/actor/1 should also work and get routed to the Id action.
-
Mihai Caracostea over 8 yearsJust make sure you've removed the other routes.
-
Arry over 8 yearsRemoved, but still same error for /api/v1/actor/id/1/ No action was found on the controller 'Actor' that matches the name '1'. Final route: config.Routes.MapHttpRoute( name: "DefaultOneLevelNested", routeTemplate: "api/v1/{controller}/{id}/{action}", defaults: new { id = "id" } );
-
Mihai Caracostea over 8 yearsUse /api/v1/actor/1 or /api/v1/actor/1/id You said the first version was acceptable.
-
Arry over 8 years/api/v1/actor/1 this will not work as I have other actions as well. It gives "Multiple actions were found that match the request". I am forced to stick with /api/v1/actor/1/id
-
Arry over 8 yearsAnd that is why I need this structure, so that I can avoid collision between same parameter type actions: /api/v1/actor/id/1/ I can also specify /api/v1/actor/born/1966/
-
Mihai Caracostea over 8 yearsThose two urls will work with this template "api/v1/{controller}/{action}/{id}"
-
Arry over 8 years:That's exactly what I have in my problem :) And it does not work. May be you can post both the routes again, so that I can try as per your say from scratch. I will share the results then.
-
Carles Company over 8 yearsUse attribute routing and you'll have less problems. Remember to use parameter constraints.