5

Here is some weird behaviour that is consistent across different actions and views in my entire website:

Whenever I POST to some action method and Model.IsValid is false, I return the view. Whenever Html.Action() is called in the view that is returned I get this exception:

(System.Web.HttpException): No matching action was found on controller 'xyz'. 

This can happen when a controller uses RouteAttribute for routing, 
but no action on that controller matches the request.

I'm using Attribute Routing.

public class RouteConfig
{
    // REGISTER ROUTES

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.MapMvcAttributeRoutes();        
    }     
}

So even though the Html.Action call worked the first time in the GET action method return View(), Html.Action always throws this exception after POST return View(). This is a general pattern across my website.

Wtf? Any ideas what's gone wrong here? The only thing I can think of is that I added more routes over time and now it's confused. How would I fix or test that if that's the case?

It just occurred to me that I have many routes/action methods where the get and post versions of routes for action methods are identical except for the GET or POST attribute on the action method. I previously made sure every route was completely unique because I was getting some ambiguity but changed it back to the same routes for get and post action methods, the only difference being the get or post attribute... I'm becoming convinced it's a routing issue but I don't know what's wrong specifically. I have route attributes on hundreds of action methods.

I have never seen anything as subtle as this before and have no idea even how to start solving something like this. I have no idea if it's simple or complicated, if it's my code or the framework. Any help would be greatly appreciated.

UPDATE:

Some sample code, not sure it will help, because the same things happens as a pattern across many utterly different action methods and views, regardless of GET, POST, authorized, unauthorized, in a role or not, antiforgerytoken...

Standard Html.Action called from a view. Works fine most of the time. (Different overloads make no difference.)

@Html.Action("CategoryDropDowns", "Category")

Here is what gets called (exactly what gets returned makes no difference, could be a ViewResult, could be an int).

// GET: /category/category-drop-downs   
[HttpGet]
[Route("category/category-drop-downs")]           
public ViewResult CategoryDropDowns()
{

}

If validation fails the view is returned:

public ActionResult CreateListing(ListDetails listDetails)
{                                       
    if (ModelState.IsValid)
    {
    }
    else
    {
        return View("List", model);
    }
}

And upon debugging through the view that gets returned, the call to Html.Action that worked fine the first time throws the exception. Same thing happens as a pattern across my website. Return View(), hit the Html.Action, bang, exception. Every time.

nmit026
  • 3,024
  • 2
  • 27
  • 53
  • You need to show the relevant code –  Oct 20 '15 at 05:29
  • See my update, for the general pattern. This code is exactly what I have for a particular action/view, but whenever the code hits a return View(), and that view contains an Html.Action(), bang, exception. Is there anything else you want to see? – nmit026 Oct 20 '15 at 05:53
  • Your routing setup also might help – Andrei Oct 20 '15 at 06:29
  • Your `@Html.Action()` uses `"CategoryDropDowns"` which is the name of the method, but then you route is `"category-drop-downs"`? –  Oct 20 '15 at 06:52
  • Sorry for being dense, but is that a problem? These action methods are only ever called by views, you can't see the url unless you use developer tools or fiddler or something if that's what you're getting at. I think the problem is I have hundreds of attribute routes in my website and something has blown up in the attribute routing part of the framework and I have no idea what. I should reiterate, browsing the site, Html.Action()s work fine. If I return View() for any reason, exception. All I can think of doing is ripping out attribute routing. Help! – nmit026 Oct 20 '15 at 07:08
  • I have a feeling some of my routes and the names of the action methods they bind to may not be completely unique, and the routing system is therefore getting confused. Will get back to you – nmit026 Oct 20 '15 at 09:20
  • It wasn't routing at all, it was the [HttpGet] attributes! – nmit026 Oct 20 '15 at 21:07

1 Answers1

13

Remove the [HttpGet] attribute from child actions!

The problem was that Html.Action() always seemed to hit an exception not after a GET, return View(), but a POST, return View().

Ages ago I went through my whole site and marked every action method that wasn't a post with the [HttpGet] attribute. I didn't realise this would cause a problem. Always test!

Removing the [HttpGet] attribute from action methods called from Html.Action() has solved the problem.

nmit026
  • 3,024
  • 2
  • 27
  • 53