nmit026
nmit026

Reputation: 3364

Asp.Net MVC5 - Html.Action - Attribute Routing - Weird Behaviour causing Exceptions

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.

Upvotes: 5

Views: 3093

Answers (1)

nmit026
nmit026

Reputation: 3364

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.

Upvotes: 14

Related Questions