间歇性的asp.net mvc异常:“在控制器XYZ上找不到公共操作方法ABC。”

时间:2009-11-16 22:12:52

标签: asp.net-mvc exception

我得到一个间歇性的例外,说asp.net mvc找不到动作方法。这是例外:

  

公共行动方法'填充'可以   在控制器上找不到   'Schoon.Form.Web.Controllers.ChrisController'。

我认为我已正确设置路由,因为此应用程序大部分时间都可以正常工作。这是控制器的动作方法。

[ActionName("Fill")]
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post), UserIdFilter, DTOFilter]
public ActionResult Fill(int userId, int subscriberId, DisplayMode? mode)
{
     //…
}

路线:

routes.MapRoute(
        "SchoonForm",
        "Form/Fill/{subscriberId}",
        new { controller = "ChrisController", action = "Fill" },
        new { subscriberId = @"\d+" }
    );

这是堆栈:

  

System.Web.HttpException:公共   动作方法'填充'不能   在控制器上找到   'Schoon.Form.Web.Controllers.ChrisController'。   在   System.Web.Mvc.Controller.HandleUnknownAction(字符串   actionName)in   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ Controller.cs:线   197年   System.Web.Mvc.Controller.ExecuteCore()   在   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ Controller.cs:线   164点   System.Web.Mvc.ControllerBase.Execute(的RequestContext   requestContext)in   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ ControllerBase.cs:线   76点   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(的RequestContext   requestContext)in   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ ControllerBase.cs:线   87点   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase   httpContext)中   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ MvcHandler.cs:线   80点   System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext的   httpContext)中   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ MvcHandler.cs:线   68点   System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext的   httpContext)中   C:\ dev的\第三方\ MvcDev \ SRC \ SystemWebMvc \的mvc \ MvcHandler.cs:线   104点   System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   在   System.Web.HttpApplication.ExecuteStep(IExecutionStep   步,布尔& completedSynchronously)

以下是我的过滤器示例,它们的工作方式相同:

public class UserIdFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        const string Key = "userId";

        if (filterContext.ActionParameters.ContainsKey(Key))
        {
            filterContext.ActionParameters[Key] = // get the user id from session or cookie
        }

        base.OnActionExecuting(filterContext);
    }
}

谢谢, 克里斯

13 个答案:

答案 0 :(得分:60)

我们找到了答案。我们调查了我们的网络日志。它表明我们收到了一些奇怪的http动作(动词/方法),如OPTIONS,PROPFIND和HEAD。

这似乎是一些例外的原因。这就解释了为什么它是断断续续的。

我们使用curl.exe工具重现了这个问题:

curl.exe -X OPTIONS http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273
curl.exe -X PROPFIND http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273
curl.exe -X HEAD http://localhost/v2.3.1.0/(S(boztz1aquhzurevtjwllzr45))/Form/Fill/273

我们使用的修复是向web.config添加授权部分:

<authorization>
  <deny users="*" verbs="OPTIONS, PROPFIND, HEAD"/>
</authorization>

答案 1 :(得分:15)

我们遇到了类似的问题,但发现它发生的原因是用户在登录超时后发布到控制器。然后系统重定向到登录屏幕。登录后,它会重定向回用户尝试发布的URL,但这次它正在执行GET请求,因此找不到标有[HttpPost]属性的操作。

答案 2 :(得分:7)

我在asp.net mvc中遇到了同样的问题。此错误 - 404未找到。我以这种方式解决问题 - 将此代码放在MyAppControllerBase(MVC)

    protected override void HandleUnknownAction(string actionName)
    {
        this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<PagesController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Pages");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

答案 3 :(得分:6)

我们在应用程序上遇到了同样的问题,我能够将其跟踪到javascript / jquery问题。我们在使用Html.ActionLink()定义的应用程序中有链接,这些链接稍后被jquery覆盖到POST中。

首先我们定义了链接:

Html.ActionLink("Click Me", "SomeAction", new { id = Model.Id})

稍后我们使用SomePostEventHandler函数覆盖默认操作:

 $(document).ready(function() {
      $('#MyLink').click(SomePostEventHandler);
 }

这是我们的MVC动作,它有一个HttpPost过滤器:

 [HttpPost]
 public ActionResult SomeAction(int id)
 {
      //Stuff
 }

我们发现,大部分时间这都很有效。但是,在一些慢速页面加载(或真正快速的用户)上,用户在jquery $(document).ready()事件被触发之前单击链接,这意味着他们正在尝试GET / Controller / SomeAction / XX而不是张贴。

我们不希望用户获取该网址,因此删除过滤器不是我们的选择。相反,我们直接连接了动作链接的onclick事件(我们必须稍微更改SomePostEventHandler()才能使其工作):

string clickEvent = "return SomePostEventHandler(this);";

Html.ActionLink("Click Me", "SomeAction", new { id = Model.Id}, new { onclick = clickEvent })

因此,至少对我们来说,故事的道德之处在于,如果您看到这些错误,请追踪您认为自己正在发布的网址,并确保确实存在。

答案 4 :(得分:2)

我也有这个问题。

在我的情况下,它与所请求操作的动词限制相关,其中视图为POST,但仅在受支持的GETHEAD内请求部分视图。将POST动词添加到AcceptVerbsAttribute(在MVC 1.0中)解决了这个问题。

答案 5 :(得分:1)

我与qq File Upload

有类似的问题

当帖子操作为/Document/Save时,我收到异常在控制器'Project.Controllers.DocumentController'上找不到公共操作方法'保存'。

但如果帖子操作为/Document/Save/,则帖子是正确的并且有效!

上帝保存 /

答案 6 :(得分:1)

从IIS日志中,我们的问题是由Googlebot尝试POST而GET仅为POST控制器操作引起的。

对于这种情况,我建议像Dmitriy建议一样处理404。

答案 7 :(得分:1)

删除[HttpGet]属性,它将起作用:)

答案 8 :(得分:1)

当前接受的答案确实按预期工作,但不是该功能的主要用例。而是使用ASP.NET定义的功能。就我而言,除了GET和POST之外,我否认了一切:

  <system.webServer>
  <security>
      <requestFiltering>
          <verbs allowUnlisted="false">
              <add verb="GET" allowed="true"/>
              <add verb="POST" allowed="true"/>
          </verbs>
      </requestFiltering>
  </security>
 </system.webServer>

使用上面的代码片段,MVC将正确返回404

答案 9 :(得分:0)

不应该是

routes.MapRoute(
        "SchoonForm",
        "Form/Fill/{subscriberId}",
        new { controller = "Chris", action = "Fill" },

此外,您的过滤器有什么作用?他们不能隐藏动作,比如ActionMethodSelectorAttribute?

答案 10 :(得分:0)

我的根本原因与评论中提到的相似。

点击一个按钮,我就是ajaxSubmitting表格。其中一个表单字段的类型为Date。但是,由于客户端和服务器计算机之间的日期格式不同,它没有在控制器中执行POST方法。服务器发回302响应,然后再次发送GET请求相同的方法。

但是,控制器中的操作是使用HttpPost属性修饰的,因此无法找到该方法并发回404响应。

我刚刚修改了代码,以便日期格式中的不匹配不会导致错误并且问题已修复。

答案 11 :(得分:0)

对于任何有angularjs问题的人,MVC和{{imagepath}}类型插入图像src属性,例如:

&#34;公共行动方法&#39; {{imagepath}} previous.png&#39;在控制器&#34;

上找不到

解决方案是使用ng-src而不是src。

希望这有助于某人:)

答案 12 :(得分:0)

查看仅浏览到所讨论的URL是否足以重现该错误。如果该动作仅被定义为POST动作,它将是这样。这样做可以让您随意重现错误。

在任何情况下,您都可以按以下方式全局处理错误。此处引用HandleUnknownAction的另一个答案仅处理具有错误操作名称而不是错误控制器名称的URL。以下方法可同时处理这两种情况。

将此添加到您的基本控制器(此处省略了查看代码):

public ActionResult Error(string errorMessage)
{
    return View("Error");  // or do something like log the error, etc.
}

将全局异常处理程序添加到Global.asax.cs中,该异常处理程序将调用上述方法或对捕获的404错误进行其他处理:

void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();  // get the exception object
    HttpException httpException = ex as HttpException;

    if (httpException != null && httpException.GetHttpCode() == 404)  // if action not found
    {
        string errorMessage = "The requested page was not found.";

        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Base");
        routeData.Values.Add("action", "Error");
        routeData.Values.Add("errorMessage", errorMessage);

        Server.ClearError();
        Response.TrySkipIisCustomErrors = true;

        // Go to our custom error view.
        IController errorController = new BaseController();
        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}