Intermittierende asp.net mvc-Ausnahme: "Eine öffentliche Aktionsmethode ABC konnte auf Controller XYZ nicht gefunden werden."

90

Ich erhalte eine zeitweise Ausnahme, die besagt, dass asp.net mvc die Aktionsmethode nicht finden kann. Hier ist die Ausnahme:

Eine öffentliche Aktionsmethode 'Fill' konnte auf dem Controller 'Schoon.Form.Web.Controllers.ChrisController' nicht gefunden werden.

Ich glaube, ich habe das Routing richtig eingerichtet, da diese Anwendung die meiste Zeit funktioniert. Hier ist die Aktionsmethode des Controllers.

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

Die Route:

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

Und hier ist der Stapel:

System.Web.HttpException: Eine öffentliche Aktionsmethode 'Fill' wurde auf dem Controller 'Schoon.Form.Web.Controllers.ChrisController' nicht gefunden. bei System.Web.Mvc.Controller.HandleUnknownAction (String actionName) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: Zeile 197 bei System.Web.Mvc.Controller.ExecuteCore () in C. : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: Zeile 164 in System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: Zeile 76 in System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: Zeile 87 bei System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase httpContext) in C:

Hier ist ein Beispiel für meine Filter, die alle auf die gleiche Weise funktionieren:

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

Danke, Chris

Chris Schoon
quelle
28
Ich hatte ein ähnliches Problem, das meiner Meinung nach hier erwähnenswert ist, da dies das erste Ergebnis war, das bei der Suche nach der oben genannten Ausnahme in Google angezeigt wurde. Meine Bewerbung hat diese Ausnahme beim Absenden eines ungültigen Formulars ausgelöst. Dies lag an der Seite, die beim Aufrufen von RenderAction (erneut) gerendert wurde, und an der Aktion, die zum Rendern einer Teilansicht aufgerufen wurde, wurde mit dem Attribut HttpGet markiert. Durch Entfernen dieses Attributs wurde das Problem behoben.
s1mm0t
3
Ich habe dieses Verhalten ebenfalls bemerkt - vielleicht ist es am besten, keine HTTP-Attribute auf Controller-Methoden anzuwenden, die PartialViewResults zurückgeben.
Stuart
1
@ s1mm0t: ist richtig. für meinen Fall löste sein Kommentar das Problem
Mazdak Shojaie
@ s1mm0t - bitte senden Sie mir umgehend Ihre Postanschrift. Eine Flasche Scotch ist dieses Weihnachten für dich unterwegs !!!!!
Shane
Wir haben etwas Ähnliches gefunden: In bestimmten Fällen verursachte die Rückgabe eines anderen Aktionsergebnisses anstelle einer Umleitung zu dieser Aktion das Problem. Ex PostSomething { return HomePageActionMethod() }schlägt fehl, wo PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }funktioniert. (In unserem Fall befindet sich die fehlerhafte Aktion in der Ansicht in einem anderen Controller, und vermutlich wird dieser Controller mit der ersten
Aufrufmethode

Antworten:

61

Wir haben die Antwort gefunden. Wir haben in unsere Weblogs geschaut. Es zeigte sich, dass wir einige seltsame http-Aktionen (Verben / Methoden) wie OPTIONS, PROPFIND und HEAD erhielten.

Dies scheint die Ursache einiger dieser Ausnahmen zu sein. Dies erklärt, warum es zeitweise war.

Wir haben das Problem mit dem Tool curl.exe reproduziert:

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

Das von uns verwendete Update bestand darin, web.config einen Autorisierungsabschnitt hinzuzufügen:

<authorization>
  <deny users="*" verbs="OPTIONS, PROPFIND, HEAD"/>
</authorization>
Chris Schoon
quelle
3
Wir haben auch festgestellt, dass Bots manchmal Ihre Website - und sogar Javascript - crawlen, um Links zu finden. Anschließend versuchen sie, Anforderungen mit dem falschen HTTP-Verb an diese URIs zu senden. Wenn Sie beispielsweise einen jQuery-Aufruf für eine Aktion haben, z. B. / some-action, und diese Methode einen POST erfordert, versucht der Bot möglicherweise, ein GET zu senden, wodurch dieser Fehler angezeigt wird. Ihre Weblogs könnten definitiv helfen, zu bestätigen, ob dies der Fall ist. Wir sehen sogar, wie Googlebot dies tut.
Jakejgordon
Ich habe denselben Fehler nur auf dem Live-Server (IIS 7.5). Die Bereitstellung funktioniert sowohl auf meinem Entwicklungscomputer als auch auf einem anderen Supportcomputer einwandfrei. Das Hinzufügen dieser Verben und das Entfernen von HttpGet hat das Problem nicht behoben. Weitere Vorschläge bitte.
Bjan
Als Alternative zum Ablehnen eingehender HEAD-Anfragen möchten Sie möglicherweise eine angemessene Antwort bereitstellen. Siehe stackoverflow.com/a/3197128/12484
Jon Schneider
15

Wir hatten ein ähnliches Problem, stellten jedoch fest, dass dies geschah, weil ein Benutzer nach Ablauf der Zeit für die Anmeldung einen Beitrag auf einem Controller veröffentlichte. Das System wurde dann zum Anmeldebildschirm umgeleitet. Nach dem Anmelden wurde es zurück zu der URL umgeleitet, unter der der Benutzer posten wollte, diesmal jedoch stattdessen eine GET-Anforderung ausführte und daher die Aktion nicht fand, die mit einem [HttpPost] -Attribut markiert war.

Johann Strydom
quelle
Meine derzeitige Lösung besteht so weit wie möglich darin, am Ende einer Aktion immer wieder zur Indexaktion zurückzukehren. Entschuldigung für die späte Antwort.
Johann Strydom
7

Ich habe das gleiche Problem in asp.net mvc. Dieser Fehler - 404 wurde nicht gefunden. Ich löse das Problem auf diese Weise - setzen Sie diesen Code in 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();
    }
Dmitriy
quelle
6

Wir hatten gerade das gleiche Problem in unserer Anwendung und ich konnte es auf ein Javascript / JQuery-Problem zurückführen. Wir haben Links in unserer Anwendung, die mit Html.ActionLink () definiert wurden und später von jquery in POSTs überschrieben werden.

Zuerst hatten wir den Link definiert:

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

Später überschreiben wir die Standardaktion mit unserer SomePostEventHandler-Funktion:

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

Dies traf unsere MVC-Aktion mit einem HttpPost-Filter:

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

Was wir fanden ist, dass dies die meiste Zeit großartig funktioniert hat. Bei einigen langsamen Seitenladevorgängen (oder sehr schnellen Benutzern) klickte der Benutzer jedoch auf den Link, bevor das Ereignis jquery $ (document) .ready () ausgelöst wurde, was bedeutet, dass er versuchte, stattdessen GET / Controller / SomeAction / XX zu verwenden Buchung.

Wir möchten nicht, dass der Benutzer diese URL erhält, daher ist das Entfernen des Filters für uns keine Option. Stattdessen haben wir das onclick-Ereignis des Aktionslinks direkt verkabelt (wir mussten SomePostEventHandler () leicht ändern, damit dies funktioniert):

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

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

Zumindest für uns ist die Moral der Geschichte, dass Sie, wenn Sie diese Fehler sehen, die URL aufspüren, an die Sie denken, dass Sie posten, und sicherstellen, dass Sie es sind.

jslatts
quelle
2

Ich hatte auch dieses Problem.

In meinem Fall handelte es sich um Verbbeschränkungen für die angeforderte Aktion, bei denen es sich bei der Ansicht um eine POSTAnsicht handelte, die jedoch nur innerhalb der unterstützten GETund angeforderten Ansicht angefordert wurde HEAD. Das Hinzufügen des POSTVerbs zu AcceptVerbsAttribute(in MVC 1.0) löste das Problem.

Wolfyuk
quelle
2

In den IIS-Protokollen wurde unser Problem dadurch verursacht, dass Googlebot POST und ein GET für eine Nur-POST-Controller-Aktion versuchte.

Für diesen Fall empfehle ich, den 404 wie Dmitriy Vorschlag zu behandeln.

Zoomen
quelle
1

Die aktuell akzeptierte Antwort funktioniert wie erwartet, ist jedoch nicht der primäre Anwendungsfall für die Funktion. Verwenden Sie stattdessen die von ASP.NET definierte Funktion. In meinem Fall habe ich alles außer GET und POST abgelehnt:

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

Mit dem obigen Code-Snippet gibt MVC einen 404 korrekt zurück

Valchris
quelle
0

Sollte es nicht sein

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

Was machen Ihre Filter? Können sie keine Aktionen wie ActionMethodSelectorAttribute ausblenden?

Königin3
quelle
Das ist ein Bearbeitungsfehler. Ich habe versucht, die Unschuldigen zu beschützen.
Chris Schoon
Sie füllen einige der Parameter. Beispielsweise ist der UserIdFilter ein Hilfsmittel zum Abrufen der Benutzer-ID aus Sitzung / Cookie / usw. Er füllt den ersten Parameter. Ich werde den Beitrag bearbeiten, um ihn aufzunehmen.
Chris Schoon
0

Ich habe das ähnliche Problem mit qq File Upload

Wenn die Post-Aktion ist, /Document/Saveerhalte ich die Ausnahme. Eine öffentliche Aktionsmethode 'Speichern' wurde auf dem Controller 'Project.Controllers.DocumentController' nicht gefunden.

Aber wenn die Post-Aktion ist /Document/Save/, ist der Post korrekt und funktioniert!

Gott schütze das / ?

Tuizi
quelle
0

Meine Grundursache war ähnlich der im Kommentar erwähnten.

Ich war ajaxSubmittingein Formular auf Knopfdruck. Eines der Formularfelder war vom Typ Date. Aufgrund der unterschiedlichen Datumsformate zwischen Client und Server wurde die POST-Methode im Controller jedoch nicht ausgeführt. Der Server hat eine 302Antwort zurückgesendet und dann erneut eine GETAnfrage für dieselbe Methode gesendet .

Die Aktion in der Steuerung wurde jedoch mit dem HttpPostAttribut versehen, sodass die Methode nicht gefunden und eine 404Antwort zurückgesendet werden konnte.

Ich habe den Code nur so behoben, dass die Nichtübereinstimmung in den Datumsformaten keinen Fehler verursacht und das Problem behoben wurde.

mridula
quelle
0

Entferne das [HttpGet] Attribute und es wird funktionieren :)

Cătălin Rădoi
quelle
Während dies die Fehler "löst", besteht die Wahrscheinlichkeit, dass Sie (oder jemand vor Ihnen) diese [HttpGet]Attribute absichtlich dort platzieren, um zu verhindern, dass die Aktionen durch andere VERBs aufgerufen werden
Nick Orlando
0

Für alle, die dieses Problem mit anglejs haben, fügen MVC- und {{imagepath}} -Typen Einfügungen in image src-Attribute ein, z.

"Eine öffentliche Aktionsmethode '{{imagepath}} previous.png' wurde auf dem Controller nicht gefunden."

Die Lösung besteht darin, ng-src anstelle von src zu verwenden.

Hoffe das hilft jemandem :)

Davaus
quelle
Fast ein Jahr später suchte ich danach :) tnx!
Verthosa
0

Überprüfen Sie, ob das einfache Navigieren zu der betreffenden URL ausreicht, um den Fehler zu reproduzieren. Dies wäre der Fall, wenn die Aktion nur als POST-Aktion definiert würde. Auf diese Weise können Sie den Fehler nach Belieben reproduzieren.

In jedem Fall können Sie den Fehler wie folgt global behandeln. Eine andere Antwort hier, die verweist, behandelt HandleUnknownActionnur URLs mit falschen Aktionsnamen, keine falschen Controllernamen. Der folgende Ansatz behandelt beide.

Fügen Sie dies Ihrem Basis-Controller hinzu (Ansichtscode hier weggelassen):

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

Fügen Sie Global.asax.cs einen globalen Ausnahmebehandler hinzu, der die oben beschriebene Methode aufruft oder mit dem abgefangenen 404-Fehler alles andere tut, was Sie möchten:

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