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


92

我收到一个间歇性异常,说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”上找不到公共操作方法“ Fill”。在System.Web.Mvc.Controller.ExecuteCore()处位于System.Web.Mvc.Controller.HandleUnknownAction(String actionName)在C:\ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs:line 197 :\ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs:C:\ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \中System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)的第164行C. \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs:第87行中System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)处的ControllerBase.cs:第76行在System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)中:

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

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);
    }
}

谢谢克里斯


28
我有一个类似的问题,我想在这里值得注意,因为这是Google在搜索上述异常时出现的第一个结果。提交无效的表单时,我的应用程序引发了此异常。这是由于正在(重新)渲染的页面上调用了RenderAction,而被调用来渲染部分视图的动作已使用HttpGet属性进行了标记,删除此属性可以解决此问题。
s1mm0t

3
我也注意到了这种现象-最好不要将任何Http属性应用于返回PartialViewResults的控制器方法。
斯图尔特(Stuart)2010年

1
@ s1mm0t:是的。对于我的情况,他的评论解决了问题
Mazdak Shojaie

@ s1mm0t-请立即将您的邮政地址发送给我。一瓶苏格兰威士忌正在这个圣诞节为您服务!!!!!
Shane

我们发现了类似的情况:在某些情况下,返回另一个操作结果而不是重定向到该操作会导致问题。防爆PostSomething { return HomePageActionMethod() }失败的地方PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }。(在我们的情况下,在视图中的违规行为位于不同的控制器,并推测该控制器没有完全与调用的第一方法初始化。
jleach

Answers:


62

我们找到了答案。我们调查了我们的网络日志。它表明我们收到了一些奇怪的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>

3
我们还发现,机器人有时有时会抓取您的网站(甚至是JavaScript)来查找链接。然后,他们尝试使用错误的HTTP动词向这些URI发送请求。例如,如果您有对某个动作的jQuery调用-例如/ some-action并且此方法需要POST,则漫游器可能会尝试发送GET,这将导致显示此错误。您的网络日志绝对可以帮助确认是否是这种情况。我们甚至看到googlebot正在这样做。
jakejgordon'3

我仅在实时服务器(IIS 7.5)上遇到相同的错误。该部署在我的开发计算机以及其他支持计算机上都可以正常工作。添加这些动词并删除HttpGet不能解决问题。任何进一步的建议,请。
bjan

除了拒绝传入的HEAD请求之外,您还可以选择提供适当的响应。参见stackoverflow.com/a/3197128/12484
乔恩·施耐德

15

我们有一个类似的问题,但发现是由于用户登录超时后将其发布到控制器而发生的。然后,系统将重定向到登录屏幕。登录后,它重定向回用户尝试发布到的URL,但是这次它执行的是GET请求,因此没有找到带有[HttpPost]属性标记的操作。


我目前的解决方案是尽可能始终在操作结束时始终重定向回Index操作。回复晚了非常抱歉。
Johann Strydom

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();
    }

6

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

首先,我们定义了链接:

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

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

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

这击中了具有HttpPost过滤器的MVC操作:

 [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 })

因此,至少对于我们来说,这个故事的寓意是,如果您看到这些错误,请跟踪您认为要发布的URL,并确保您是。


2

我也有这个问题。

在我的情况下,它是关系到所请求的动作动词的限制,这里的观点是POST,但所请求的局部视图中支持GETHEAD唯一的。将POST动词添加到中AcceptVerbsAttribute(在MVC 1.0中)解决了该问题。


2

在IIS日志中,我们的问题是由Googlebot尝试执行POST和仅执行POST控制器操作的GET引起的。

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


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


0

不是吗

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

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


那是一个编辑错误。我试图保护无辜者。
克里斯·舒恩

它们填充了一些参数。例如,UserIdFilter是从会话/ cookie /等获取用户ID的助手。它填充第一个参数。我将编辑该帖子以包含它。
克里斯·舒恩

0

我在qq文件上传中遇到类似的问题

当发布动作是/Document/Save异常时,在控制器“ Project.Controllers.DocumentController”上找不到公共动作方法“保存”。

但是,如果发布操作为/Document/Save/,则发布正确且有效!

上帝救了/


0

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

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

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

我只是修复了代码,以使Date格式中的不匹配不会导致错误,并且问题已得到解决。


0

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


尽管这“解决”了错误,但可能是您(或您之前的某人)[HttpGet]故意将那些属性放在此处,以防止通过任何其他VERB调用该操作
Nick Orlando

0

对于有人对angularjs,MVC和{{imagepath}}有此问题的人,请在image src属性中插入类型,例如:

“在控制器上找不到公共操作方法'{{imagepath}} previous.png'”

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

希望这可以帮助某人:)


差不多一年后,我正在寻找这个:) tnx!
Verthosa

0

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

在任何情况下,您都可以按以下方式全局处理该错误。此处引用的另一个答案HandleUnknownAction仅处理具有错误操作名称的URL,而不处理具有错误控制器名称的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));
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.