Eccezione intermittente asp.net mvc: "Impossibile trovare un metodo di azione pubblica ABC sul controller XYZ."


92

Ricevo un'eccezione intermittente dicendo che asp.net mvc non riesce a trovare il metodo di azione. Ecco l'eccezione:

Impossibile trovare un metodo di azione pubblica "Fill" sul controller "Schoon.Form.Web.Controllers.ChrisController".

Penso di aver impostato correttamente il routing perché questa applicazione funziona la maggior parte del tempo. Ecco il metodo di azione del controller.

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

La strada:

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

Ed ecco lo stack:

System.Web.HttpException: Impossibile trovare un metodo di azione pubblica "Fill" sul controller "Schoon.Form.Web.Controllers.ChrisController". in System.Web.Mvc.Controller.HandleUnknownAction (String actionName) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: riga 197 in System.Web.Mvc.Controller.ExecuteCore () in C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: riga 164 in System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: riga 76 in System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) in C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: riga 87 in System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase httpContext) in C:

Ecco un esempio dei miei filtri funzionano tutti allo stesso modo:

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

Grazie, Chris


28
Ho avuto un problema simile che penso valga la pena notare qui poiché questo è stato il primo risultato che è emerso in Google durante la ricerca dell'eccezione sopra. La mia domanda ha generato questa eccezione quando ha inviato un modulo non valido. Ciò era dovuto al fatto che la pagina era stata (ri) renderizzata chiamando RenderAction e l'azione chiamata per eseguire il rendering di una vista parziale era contrassegnata con l'attributo HttpGet, la rimozione di questo attributo ha risolto il problema.
s1mm0t

3
Ho notato anche questo comportamento, forse è meglio non applicare alcun attributo Http ai metodi del controller che restituiscono PartialViewResults.
Stuart

1
@ s1mm0t: ha ragione. per il mio caso, il suo commento ha risolto il problema
Mazdak Shojaie

@ s1mm0t - inviami immediatamente il tuo indirizzo postale. Una bottiglia di Scotch è in arrivo per te questo Natale !!!!!
Shane

Abbiamo trovato qualcosa di simile: in alcuni casi la causa del problema era restituire un altro risultato dell'azione invece di un reindirizzamento a quell'azione. Ex PostSomething { return HomePageActionMethod() }fallisce dove PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }funziona. (nel nostro caso l'azione incriminata nella vista si trova in un controller diverso, e presumibilmente quel controller non è completamente inizializzato con il primo metodo di chiamata.
jleach

Risposte:


62

Abbiamo trovato la risposta. Abbiamo esaminato i nostri registri web. Ha mostrato che stavamo ricevendo alcune strane azioni http (verbi / metodi) come OPTIONS, PROPFIND e HEAD.

Questo sembra essere la causa di alcune di queste eccezioni. Questo spiega perché era intermittente.

Abbiamo riprodotto il problema con lo strumento 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

La correzione che abbiamo utilizzato è stata l'aggiunta di una sezione di autorizzazione a web.config:

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

3
Abbiamo anche scoperto che a volte i bot eseguono la scansione del tuo sito, e persino di javascript, per trovare collegamenti. Quindi provano a inviare richieste a questi URI con il verbo HTTP sbagliato. Ad esempio, se hai una chiamata jQuery per un'azione, ad esempio / some-action e questo metodo richiede un POST, il bot potrebbe tentare di inviare un GET, il che causerà la visualizzazione di questo errore. I tuoi registri web potrebbero sicuramente aiutare a confermare se questo fosse il caso. Vediamo persino Googlebot che lo fa.
jakejgordon

Sto riscontrando lo stesso errore solo sul server Live (IIS 7.5). La distribuzione funziona correttamente sulla mia macchina di sviluppo e su un'altra macchina di supporto. l'aggiunta di questi verbi e la rimozione di HttpGet non hanno risolto il problema. Ulteriori suggerimenti per favore.
bjan

In alternativa al rifiuto delle richieste HEAD in arrivo, potresti voler fornire una risposta appropriata. Vedi stackoverflow.com/a/3197128/12484
Jon Schneider

15

Abbiamo riscontrato un problema simile, ma abbiamo scoperto che stava accadendo perché un utente stava postando su un controller dopo che il suo accesso era scaduto. Il sistema è quindi stato reindirizzato alla schermata di accesso. Dopo aver effettuato l'accesso, è stato reindirizzato all'URL a cui l'utente stava tentando di postare, ma questa volta stava invece effettuando una richiesta GET e quindi non ha trovato l'azione contrassegnata con un attributo [HttpPost].


La mia soluzione attuale è, per quanto possibile, fare sempre un reindirizzamento all'azione Indice alla fine di un'azione. Scusa per la risposta in ritardo.
Johann Strydom

7

Ho lo stesso problema in asp.net mvc. questo errore - 404 non trovato. Risolvo il problema in questo modo: inserisci questo codice 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();
    }

6

Abbiamo appena avuto lo stesso problema sulla nostra applicazione e sono stato in grado di risalire a un problema di javascript / jquery. Abbiamo collegamenti nella nostra applicazione definiti utilizzando Html.ActionLink () che vengono successivamente sovrascritti in POST da jquery.

Per prima cosa avevamo definito il collegamento:

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

Successivamente sovrascriviamo l'azione predefinita con la nostra funzione SomePostEventHandler:

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

Questo stava colpendo la nostra azione MVC che aveva un filtro HttpPost:

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

Quello che abbiamo scoperto è che la maggior parte delle volte ha funzionato alla grande. Tuttavia, su alcuni caricamenti di pagine lenti (o utenti molto veloci), l'utente stava facendo clic sul collegamento prima che si attivasse l'evento jquery $ (document) .ready (), il che significa che stava tentando di GET / Controller / SomeAction / XX invece di distacco.

Non vogliamo che l'utente OTTIENI quell'URL, quindi rimuovere il filtro non è un'opzione per noi. Invece abbiamo semplicemente cablato l'evento onclick del collegamento dell'azione direttamente (abbiamo dovuto modificare leggermente SomePostEventHandler () affinché funzionasse):

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

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

Quindi, la morale della storia, almeno per noi, è che se stai vedendo questi errori, rintraccia l'URL a cui PENSI di stare POSTANDO e assicurati di esserlo.


2

Anch'io ho avuto questo problema.

Nel mio caso era correlato alle restrizioni verbali sull'azione richiesta, dove la vista era una POSTma la vista parziale richiesta all'interno di supportati GETe HEADsolo. L'aggiunta del POSTverbo a AcceptVerbsAttribute(in MVC 1.0) ha risolto il problema.


2

Dai log di IIS il nostro problema è stato causato da Googlebot che ha tentato di eseguire il POST e un GET per un'azione del controller solo POST.

Per questo caso consiglio di gestire il 404 come il suggerimento di Dmitriy.


1

La risposta attualmente accettata funziona come previsto ma non è il caso di utilizzo principale della funzionalità. Utilizzare invece la funzionalità definita da ASP.NET. Nel mio caso, ho negato tutto tranne GET e POST:

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

Con lo snippet di codice precedente, MVC restituirà correttamente un 404


0

Non dovrebbe essere

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

Inoltre, cosa fanno i tuoi filtri? Non possono nascondere azioni, come ActionMethodSelectorAttribute?


Questo è un errore di modifica. Stavo cercando di proteggere gli innocenti.
Chris Schoon

Popolano alcuni parametri. Ad esempio, UserIdFilter è un helper per ottenere l'ID utente dalla sessione / cookie / ecc. Popola il primo parametro. Modificherò il post per includerlo.
Chris Schoon,

0

Ho il problema simile con qq File Upload

Quando l'azione del post è /Document/Saveottengo l'eccezione Un metodo di azione pubblica "Salva" non è stato trovato sul controller "Project.Controllers.DocumentController".

Ma se l'azione del post è /Document/Save/, il post è corretto e funziona!

Dio salvi il / ?


0

La mia causa principale era simile a quella menzionata nel commento.

Ero ajaxSubmittingun modulo al clic di un pulsante. Uno dei campi del modulo era di tipo Date. Tuttavia, a causa della differenza nei formati di data tra la macchina client e server, non ha eseguito il metodo POST nel controller. Il server ha restituito una 302risposta e quindi ha inviato di nuovo una GETrichiesta per lo stesso metodo.

Tuttavia, l'azione nel controller è stata decorata con l' HttpPostattributo e quindi non è stato possibile trovare il metodo e restituire una 404risposta.

Ho appena corretto il codice in modo tale che la mancata corrispondenza nei formati Data non causasse un errore e il problema è stato risolto.


0

Rimuovi gli [HttpGet]attributi e funzionerà :)


Anche se questo "risolve" gli errori, è probabile che tu (o qualcuno prima di te) inserisca questi [HttpGet]attributi lì apposta, per evitare che le azioni vengano chiamate attraverso altri VERBI
Nick Orlando

0

Per chiunque abbia questo problema con angularjs, inserimenti di tipo MVC e {{imagepath}} negli attributi src dell'immagine, ad esempio:

"Un metodo di azione pubblica '{{imagepath}} previous.png' non è stato trovato sul controller"

La soluzione è usare ng-src invece di src.

Spero che questo aiuti qualcuno :)


quasi un anno dopo, stavo cercando questo :) tnx!
Verthosa

0

Verifica se la semplice navigazione all'URL in questione è sufficiente per riprodurre l'errore. Lo sarebbe se l'azione fosse definita solo come azione POST. In questo modo è possibile riprodurre l'errore a piacimento.

In ogni caso, puoi gestire globalmente l'errore come di seguito. Un'altra risposta qui che fa riferimento HandleUnknownActiongestisce solo gli URL con nomi di azioni errati, non nomi di controller errati. Il seguente approccio gestisce entrambi.

Aggiungilo al controller di base (visualizza il codice omesso qui):

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

Aggiungi un gestore di eccezioni globale a Global.asax.cs che chiama il metodo sopra o fa qualsiasi altra cosa tu voglia fare con l'errore 404 rilevato:

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));
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.