4

I have just encountered a strange problem. I have fixed it, but I am hoping that you may be able to help me better understand what actually went wrong. I'll start with an explanation of what happened. The problem concerns a simple MVC3 RC1 app.

In my app's master page there is a call to an action on a controller to render a login-form:

@Html.Action("LoginForm", "Account")

The action method on the AccountController class returns a PartialViewResult containing the login-form.

public PartialViewResult LoginForm()
{
    return PartialView();
}

Today I made a change to this action method and attributed it with the HttpGetAttribute like so:

[HttpGet]
public PartialViewResult LoginForm()
{
    return PartialView();
}

This is what caused problems. However, the problems only existed in one particular scenario - and this is what baffles me. When posting a form to a controller everything would work just fine provided that the controller action then returned a RedirectToRouteResult. If the action just returned a ViewResult (to its default view), my Http404 error handling would kick in and loop forever.

I have implemented 404 error handling in a manner very similar to what is described in the third answer to this question: Requirements for 404. If you don't want to read that post, in simple terms I override the HandleUnknownAction method on my base controller class, and in that method I instantiate an instance of my ErrorController class and call Execute on it, passing it an instance of RouteData:

protected override void HandleUnknownAction(string actionName)
{
    // If controller is ErrorController dont 'nest' exceptions
    if (this.GetType() != typeof(ErrorController))
        this.InvokeHttp404(HttpContext);
}

public ActionResult InvokeHttp404(HttpContextBase httpContext)
{
    IController errorController = DependencyResolver.Current.GetService<ErrorController>();

    var errorRoute = new RouteData();
    errorRoute.Values.Add("controller", "Error");
    errorRoute.Values.Add("action", "Http404");
    errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
    errorController.Execute(new RequestContext(httpContext, errorRoute));

    return new EmptyResult();
}

All the ErrorController does is log the error and return a view with a friendly error message. Well, that's how it should work. But in this case the error handling would enter into an infinite loop where the AccountController (to which my form was posted) would invoke the HandleUnknownAction over and over and over again.

There was nothing in the error logs to indicate what had gone wrong (I think I log just about everything) - which was also strange. So I figured that if removed the HandleUnknownAction method from my controller base class maybe something else would be revealed. And it was:

2010-12-10 19:11:47,956 [4] ERROR Infrastructure.Log4NetAuditor [System.Web.HttpException (0x80004005): Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'. ---> System.Web.HttpException (0x80004005): Execution of the child request failed. Please examine the InnerException for more information. ---> System.Web.HttpException (0x80004005): A public action method 'LoginForm' was not found on controller 'Cdo.Web.Controllers.AccountController'.

What the? When I saw this I remembered that I'd put the HttpGetAttribute on this method - so I promptly removed it... and order was restored. I am happy to have discovered what caused this - but I remain in the dark on why it happened. If you are able to help me shed some light on this I'd be much obliged. Why would the HttpGetAttribute make a difference here?

Community
  • 1
  • 1
Øyvind
  • 1,600
  • 1
  • 14
  • 33
  • 1
    its hard to follow the case above. "However, the problems only existed in one particular scenario - and this is what baffles me. When posting a form to a controller everything would work just fine provided that the controller action then returned a RedirectToRouteResult. If the action just returned a ViewResult (to its default view), my Http404 error handling would kick in and loop forever." which action. "a form" is referenced. Which form? when posting what to what controller method? are you trying to post to the same method? The LoginForm view reposits to which action? is there a prob there? – Adam Tuliper Oct 03 '11 at 01:29

1 Answers1

0

try setting outputcache attribute to action. I remember that kind of problem and this was a solution. set duration on 1

[OutputCache(Duration = 1, VaryByParam = "None")]
karaxuna
  • 26,752
  • 13
  • 82
  • 117