web-dev-qa-db-fra.com

Exception intermittente asp.net mvc: "Une méthode d'action publique ABC est introuvable sur le contrôleur XYZ"

Je reçois une exception intermittente disant qu'asp.net mvc ne peut pas trouver la méthode d'action. Voici l’exception:

Une méthode d'action publique 'Remplir' pourrait ne pas être trouvé sur le contrôleur 'Schoon.Form.Web.Controllers.ChrisController'.

Je pense que le routage est correctement configuré car cette application fonctionne la plupart du temps. Voici la méthode d’action du contrôleur.

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

La route:

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

Et voici la pile:

System.Web.HttpException: un public La méthode d'action 'Remplir' ne peut pas être trouvé sur le contrôleur 'Schoon.Form.Web.Controllers.ChrisController' . à System.Web.Mvc.Controller.HandleUnknownAction (String ActionName) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\Controller.cs: ligne 197 at System.Web.Mvc.Controller.ExecuteCore () dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\Controller.cs: ligne 164 at System.Web.Mvc.ControllerBase.Execute (RequestContext RequestContext) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\ControllerBase.cs: ligne 76 at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext RequestContext) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\ControllerBase.cs: ligne 87 at System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase HttpContext) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\MvcHandler.cs: ligne 80 at System.Web.Mvc.MvcHandler.ProcessRequest (HttpContext HttpContext) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\MvcHandler.cs: ligne 68 at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest (HttpContext HttpContext) dans C:\dev\ThirdParty\MvcDev\src\SystemWebMvc\Mvc\MvcHandler.cs: ligne 104 at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () à System.Web.HttpApplication.ExecuteStep (IExecutionStep Step, Boolean & completedSynchronously)

Voici un exemple de mes filtres, ils fonctionnent tous de la même manière:

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

Merci, Chris

87
Chris Schoon

Nous avons trouvé la réponse. Nous avons examiné nos journaux Web. Cela montrait que nous recevions des actions http étranges (verbes/méthodes) comme OPTIONS, PROPFIND et HEAD.

Cela semble être la cause de certaines de ces exceptions. Cela explique pourquoi c'était intermittent.

Nous avons reproduit le problème avec l'outil 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

Le correctif que nous avons utilisé consistait à ajouter une section d'autorisation à web.config:

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

Nous avions un problème similaire, mais nous avons constaté que cela se produisait car un utilisateur publiait sur un contrôleur après l'expiration de son identifiant. Le système a ensuite été redirigé vers l'écran de connexion. Après s'être connecté, il a été redirigé vers l'URL à laquelle l'utilisateur essayait de se connecter, mais cette fois, il faisait une requête GET et ne trouvait donc pas l'action marquée d'un attribut [HttpPost].

15
Johann Strydom

J'ai le même problème dans asp.net mvc. cette erreur - 404 non trouvée. Je résous le problème de cette façon - mettez ce code dans 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();
    }
7
Dmitriy

Nous venons d'avoir le même problème sur notre application et j'ai été en mesure de le retracer à un problème lié à javascript/jquery. Nous avons des liens dans notre application définis à l'aide de Html.ActionLink () qui sont ensuite remplacés par des requêtes POST par jquery. 

Nous avions d'abord défini le lien:

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

Plus tard, nous remplaçons l'action par défaut avec notre fonction SomePostEventHandler:

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

Cela frappait notre action MVC qui avait un filtre HttpPost:

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

Nous avons constaté que la plupart du temps, cela fonctionnait très bien. Cependant, lors de certains chargements de page lents (ou utilisateurs très rapides), l’utilisateur cliquait sur le lien avant l’événement jquery $ (document) .ready (), ce qui signifie qu’il essayait d’obtenir GET/Controller/SomeAction/XX au lieu de affectation.

Nous ne voulons pas que l'utilisateur obtienne cette URL, aussi la suppression du filtre n'est pas une option pour nous. Au lieu de cela, nous avons simplement câblé l'événement onclick du lien d'action directement (nous avons dû modifier légèrement SomePostEventHandler () pour que cela fonctionne):

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

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

Donc, la morale de l'histoire, du moins pour nous, est que si vous voyez ces erreurs, localisez l'URL que vous pensez que vous publiez et assurez-vous de l'être.

6
jslatts

Moi aussi j'ai eu ce problème. 

Dans mon cas, il était lié aux restrictions de verbe sur l'action demandée, où la vue était une POST mais la vue partielle étant demandée uniquement dans GET et HEAD prises en charge. L'ajout du verbe POST à la AcceptVerbsAttribute (dans MVC 1.0) a résolu le problème.

2
WolfyUK

La réponse actuellement acceptée fonctionne comme prévu, mais ne constitue pas le principal cas d'utilisation de la fonctionnalité. Utilisez plutôt la fonctionnalité définie par ASP.NET. Dans mon cas, j'ai tout refusé sauf GET et POST:

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

Avec l’extrait de code ci-dessus, MVC renverra correctement un message 404.

1
Valchris

J'ai le même problème avec qq File Upload

Lorsque l'action post est /Document/Save, je reçois l'exception Une méthode d'action publique "Enregistrer" est introuvable sur le contrôleur "Project.Controllers.DocumentController".

Mais si l'action post est /Document/Save/, la publication est correcte et fonctionne!

Dieu sauve le /?

1
Tuizi

Dans les journaux IIS, notre problème était dû à la tentative de Googlebot POST et à un test GET pour une action de contrôleur POST uniquement.

Pour ce cas, je recommande de manipuler la suggestion 404 comme Dmitriy.

1
Zoom

Supprimez les attributs [HttpGet] et cela fonctionnera :)

0
Cătălin Rădoi

Ma cause fondamentale était semblable à celle mentionnée dans le commentaire. 

J'étais ajaxSubmitting un formulaire en cliquant sur un bouton. L'un des champs du formulaire était de type Date. Toutefois, en raison de la différence de format de date entre le client et le serveur, il n’a pas exécuté la méthode POST dans le contrôleur. Le serveur a renvoyé une réponse 302, puis à nouveau une requête GET pour la même méthode. 

Cependant, l'action dans le contrôleur a été décorée avec l'attribut HttpPost. Par conséquent, il n'a pas pu trouver la méthode et a renvoyé une réponse 404.

Je viens de corriger le code de telle sorte que l'incompatibilité dans les formats de date ne provoque pas d'erreur et le problème a été corrigé.

0
mridula

Ça ne devrait pas être

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

Aussi, que font vos filtres? Ne peuvent-ils pas cacher l'action, comme ActionMethodSelectorAttribute?

0
queen3

Pour ceux qui ont ce problème avec angularjs, MVC et les insertions de type {{imagepath}} dans les attributs d’image src, par exemple:

"Une méthode d'action publique '{{imagepath}} previous.png' n'a pas été trouvée sur le contrôleur"

La solution consiste à utiliser ng-src au lieu de src.

J'espère que ça aide quelqu'un :)

0
davaus

Vérifiez que le simple fait de naviguer vers l'URL en question suffit à reproduire l'erreur. Ce serait le cas si l'action était uniquement définie comme une action POST. Cela vous permet de reproduire l'erreur à volonté.

Dans tous les cas, vous pouvez gérer globalement l'erreur comme indiqué ci-dessous. Une autre réponse qui fait référence à HandleUnknownAction ne traite que les URL avec des noms d’action incorrects, pas de noms de contrôleur incorrects. L'approche suivante gère les deux.

Ajoutez ceci à votre contrôleur de base (voir le code omis ici):

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

Ajoutez un gestionnaire d'exception global à Global.asax.cs qui appelle la méthode ci-dessus ou effectue tout ce que vous voulez faire avec l'erreur 404 interceptée:

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));
    }
}
0
Tawab Wakil