1

I have a controller with two POST methods:

[WebInvoke(Method = "POST", UriTemplate = "/api/controller/action1")]
[ActionName("action1")]
public HttpResponseMessage MethodA(string s1, string s2);

[WebInvoke(Method = "POST", UriTemplate = "/api/controller/action2")]
[ActionName("action2")]
public HttpResponseMessage MethodB(string s1, InternalClass c);

I'm calling it from a test harness. When I try to POST to MethodB using the URL http://localhost/api/controller?s1=<string>, passing c in the body of the POST, the message indicates that it's trying to call MethodA instead (I have a validation filter that indicates "s1 and s2 are required fields").

When I add the action to the URL and try to POST to MethodB using http://localhost/api/controller/action2?s1=<string>, passing c in the body, I get a 404 instead.

I modified my RouteConfig to use these routes:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapHttpRoute(
  name: "Name1",
  routeTemplate: "api/{controller}"
);

routes.MapHttpRoute(
  name: "Name2",
  routeTemplate: "api/{controller}/{id}",
  defaults: null,
  constraints: new { id = @"^\d+$" } // Only integers 
);

routes.MapHttpRoute(
  name: "Name3",
  routeTemplate: "api/{controller}/{action}"
);

routes.MapRoute(
  name: "Default",
  url: "api/{controller}/{action}/{id}",
  defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);

as was indicated in this question.

What am I doing wrong?

Community
  • 1
  • 1
Adam V
  • 6,256
  • 3
  • 40
  • 52

1 Answers1

2

When I try to POST to MethodB using the URL http://localhost/api/controller?s1=<string>, passing c in the body of the POST, the message indicates that it's trying to call MethodA instead (I have a validation filter that indicates "s1 and s2 are required fields").

It sounds like you're trying to rely on overloading to disambiguate your routes -- MVC doesn't work like this. You have to make sure your routes are defined to be unique, with a single POST and GET per route.

In this case, the default action method for /api/controller is MethodA, and it's trying to force object C into the second parameter of MethodA.

If you want the default to go to MethodB, you will have to update your route. However, it sounds like you want it to be dynamic and figure out the route based on the parameters being posted, and it doesn't work like that.

Also, this route:

routes.MapRoute(
  name: "Default",
  url: "api/{controller}/{action}/{id}",
  defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);

Looks wrong, because it's pointing to the Default controller, Index action method, which you don't have listed in your code. So going to api/controller will try to go to Default.Index.

Lastly, consider the order of your routes. When the MVC pipeline evaluates your routes, it will match the first possible route. In your case, you have the more generic routes at the top, with the more specific routes at the bottom. You need to reorder these, putting the more specific routes at the top. This article talks about this.

Jerad Rose
  • 15,235
  • 18
  • 82
  • 153
  • So I can't disambiguate by using the actions? – Adam V Nov 08 '13 at 20:44
  • Yes, but not the parameters. Using the actions in the URL should work. What happens if you hard-code your routes, having two actions, one for each method? It sounds like you have something else wrong (outside of the code you've listed), so need to troubleshoot more. – Jerad Rose Nov 08 '13 at 20:44
  • I'll try hardcoding these routes now. But does the order of the routes matter? If I moved "Name3" (with controller and action) above "Name1" (with just controller), would it take precedence? – Adam V Nov 08 '13 at 20:46
  • Ah yes, that's it. It's matching that second route. I would get rid of that one for now. – Jerad Rose Nov 08 '13 at 20:48
  • Actually, never mind, that route should not be matching, with the constraint. That's the point of the constraint. – Jerad Rose Nov 08 '13 at 20:50
  • I reordered the routes to move "Name1" below "Name2" and "Name3", and now the system is taking the Action into account. Thanks for your help! – Adam V Nov 08 '13 at 21:10
  • Awesome, I'll update the answer for future reference of others. – Jerad Rose Nov 08 '13 at 21:19