Html.Action 使用 [HttpGet] 属性调用操作时出现问题

发布于 2024-10-07 01:42:08 字数 2526 浏览 7 评论 0原文

我刚刚遇到一个奇怪的问题。我已经修复了它,但我希望您能够帮助我更好地了解到底出了什么问题。我将首先解释所发生的事情。该问题涉及一个简单的 MVC3 RC1 应用程序。

在我的应用程序的母版页中,调用控制器上的操作来呈现登录表单:

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

AccountController 类上的操作方法返回包含登录表单的 PartialViewResult。

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

今天我对此操作方法进行了更改,并将其归因于 HttpGetAttribute,如下所示:

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

这就是导致问题的原因。然而,这些问题只存在于一种特定的情况下——这就是让我困惑的地方。当发布表单到控制器时,只要控制器操作返回RedirectToRouteResult,一切都会正常工作。如果该操作仅返回一个ViewResult(到其默认视图),我的 Http404 错误处理将启动并永远循环。

我已经以与此问题的第三个答案中描述的方式非常相似的方式实现了 404 错误处理: 404 的要求。如果您不想阅读该文章,简单来说,我会重写基本控制器类上的 HandleUnknownAction 方法,并在该方法中实例化 ErrorController 类的实例并对其调用 Execute,并向其传递 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();
}

ErrorController 所做的只是记录错误并返回带有友好错误消息的视图。嗯,这就是它应该如何工作的。但在这种情况下,错误处理将进入无限循环,其中 AccountController(我的表单发布到其中)将一遍又一遍地调用 HandleUnknownAction。

错误日志中没有任何内容表明出了什么问题(我想我只记录了所有内容) - 这也很奇怪。所以我想,如果从我的控制器基类中删除 HandleUnknownAction 方法,也许会显示其他内容。它是:

2010-12-10 19:11:47,956 [4] ERROR Infrastructure.Log4NetAuditor [System.Web.HttpException (0x80004005): 执行处理程序“System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper”的子请求时出错'。 ---> System.Web.HttpException (0x80004005):子请求执行失败。请检查 InnerException 以获取更多信息。 ---> System.Web.HttpException(0x80004005):在控制器“Cdo.Web.Controllers.AccountController”上找不到公共操作方法“LoginForm”。

什么?当我看到这个时,我记得我将 HttpGetAttribute 放在这个方法上 - 所以我立即将其删除......并且顺序恢复了。我很高兴发现了造成这种情况的原因 - 但我仍然不知道为什么会发生这种情况。如果您能够帮助我阐明这一点,我将不胜感激。为什么 HttpGetAttribute 会在这里产生影响?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苏辞 2024-10-14 01:42:08

尝试将outputcache属性设置为action。我记得有这样的问题,这是一个解决方案。将持续时间设置为 1

[OutputCache(Duration = 1, VaryByParam = "None")]

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")]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文