Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

404 - A public action method X was not found on controller Y (ActionInvoker.InvokeAction returns false)

This is NOT a duplicate question, and the problem is driving me crazy. I am getting the typical error "A public action method X was not found on controller Y" which returns a 404 Not Found. The screenshot gives you a good idea:

Visual Studio debugging session

The image shows the debugger paused right before the line that throws the exception is executed (base.HandleUnknownAction(actionName)). Now, before you jump into conclusions, here's some info:

  1. This was working at some point perfectly well.
  2. The HTTP verb (GET) should be accepted by the UpdateCart action (see annotations above method signature).
  3. The parameters sent are irrelevant: the error happens with POST, GET and any combination of parameters.
  4. Other similar actions in the same controller work well.
  5. I took the screenshot with UpdateCart marked virtual, but removing virtual makes no difference.
  6. The screenshot shows that ActionInvoker.InvokeAction(this.ControllerContext, "UpdateCart") returns false. Not sure why the reflection performed over my controller can't find the method, but it's RIGHT THERE!!

The routes are the default ones and they work, since otherwise I wouldn't have been able to stop the debugger to take the screenshot above. Here's the code from Global.asax.cs:

public static void RegisterRoutes(RouteCollection routes) {     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");      routes.MapRoute(         "Default", // Route name         "{controller}/{action}/{id}", // URL with parameters         new { controller = "Tickets", action = "Index", id = UrlParameter.Optional }      );  } 

Any ideas are greatly appreciated.

EDIT

Ethan Brown's answer below is correct: HttpGet and HttpPost are mutually exclusive. The solution was to replace these attributes with [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)].

like image 823
Diego Avatar asked Mar 29 '12 18:03

Diego


2 Answers

The problem is that you're specifying both the HttpGet and HttpPost attributes. If you leave both of them off, the action accepts both POST and GET requests. My guess is that the HttpGet and HttpPost attributes don't signal to MVC to allow the corresponding request type, but to deny the opposite type. So by including [HttpPost], you're denying GET requests, and by including [HttpGet], you're denying POST requests...effectively denying all request types. Leave the attributes off and it will accept both types.

Update: I just checked the MVC source, and my assumption is correct. In ActionMethodSelector, it checks the attributes thusly:

if (attrs.All(attr => attr.IsValidForRequest(controllerContext, methodInfo))) {     matchesWithSelectionAttributes.Add(methodInfo); } 

In other words, all ActionMethodSelectorAttribute (from which HttpPostAttribute and HttpGetAttribute derive) must return true for the action to be invoked. One or the other is always going to return false, so the action will never execute.

like image 154
Ethan Brown Avatar answered Sep 23 '22 00:09

Ethan Brown


Watch out: in my case I was getting a 500 error when trying to reach a new action method.

IIS 8.5 Detailed Error - 500.0 - A public action method 'getwells' was not found on controller 'ITVizion.VizionLogs.Widgets.Controllers.MapController'.

I added the action method to the Controller and was "deploying" the updated app to IIS.

The problem: I was deploying the Debug configuration in Visual Studio and had unchecked that specific project from building. That was to speed up building in Visual Studio since there are lots of project in the solution. :D Going to the IIS app folder I saw that the project's DLL was outdated.

So make sure you check the project to Build. :) This will obviously take care of deploying the new codez to IIS.

enter image description here

like image 30
Leniel Maccaferri Avatar answered Sep 21 '22 00:09

Leniel Maccaferri