Excepción intermitente de asp.net mvc: "No se pudo encontrar un método de acción pública ABC en el controlador XYZ".

92

Recibo una excepción intermitente que dice que asp.net mvc no puede encontrar el método de acción. Esta es la excepción:

No se pudo encontrar un método de acción pública 'Fill' en el controlador 'Schoon.Form.Web.Controllers.ChrisController'.

Creo que tengo el enrutamiento configurado correctamente porque esta aplicación funciona la mayor parte del tiempo. Aquí está el método de acción del controlador.

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

La ruta:

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

Y aquí está la pila:

System.Web.HttpException: No se pudo encontrar un método de acción pública 'Fill' en el controlador 'Schoon.Form.Web.Controllers.ChrisController'. en System.Web.Mvc.Controller.HandleUnknownAction (String actionName) en C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: línea 197 en System.Web.Mvc.Controller.ExecuteCore () en C : \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ Controller.cs: línea 164 en System.Web.Mvc.ControllerBase.Execute (RequestContext requestContext) en C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: línea 76 en System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute (RequestContext requestContext) en C: \ dev \ ThirdParty \ MvcDev \ src \ SystemWebMvc \ Mvc \ ControllerBase.cs: línea 87 en System.Web.Mvc.MvcHandler.ProcessRequest (HttpContextBase httpContext) en C:

Aquí hay un ejemplo de mis filtros, todos funcionan de la misma manera:

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

Gracias Chris

Chris Schoon
fuente
28
Tuve un problema similar que creo que vale la pena señalar aquí, ya que este fue el primer resultado que apareció en Google al buscar la excepción anterior. Mi aplicación arrojó esta excepción al enviar un formulario no válido. Esto se debió a que la página se estaba (re) renderizando llamando a RenderAction y la acción que se llamó para renderizar una vista parcial se marcó con el atributo HttpGet, la eliminación de este atributo resolvió el problema.
s1mm0t
3
También he notado este comportamiento; quizás sea mejor no aplicar ningún atributo Http a los métodos del controlador que devuelven PartialViewResults.
Stuart
1
@ s1mm0t: tiene razón. para mi caso, su comentario resolvió el problema
Mazdak Shojaie
@ s1mm0t: envíeme su dirección postal inmediatamente. ¡Una botella de whisky está en camino para ti esta Navidad!
Shane
Encontramos algo similar: en ciertos casos, devolver otro resultado de acción en lugar de una redirección a esa acción estaba causando el problema. Ex PostSomething { return HomePageActionMethod() }falla donde PostSomething { return RedirectToAction(nameof(HomePageActionMethod)); }trabaja. (en nuestro caso, la acción ofensiva en la vista se encuentra en un controlador diferente, y presumiblemente ese controlador no está completamente inicializado con el primer método de llamada.
jleach

Respuestas:

62

Encontramos la respuesta. Examinamos nuestros registros web. Demostró que estábamos recibiendo algunas acciones http extrañas (verbos / métodos) como OPTIONS, PROPFIND y HEAD.

Esto parece ser la causa de algunas de estas excepciones. Esto explica por qué fue intermitente.

Reproducimos el problema con la herramienta 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 solución que usamos fue agregar una sección de autorización a web.config:

<authorization>
  <deny users="*" verbs="OPTIONS, PROPFIND, HEAD"/>
</authorization>
Chris Schoon
fuente
3
También descubrimos que, en ocasiones, los bots rastrearán su sitio, e incluso javascript, para encontrar enlaces. Luego intentan enviar solicitudes a estos URI con el verbo HTTP incorrecto. Por ejemplo, si tiene una llamada de jQuery a alguna acción, por ejemplo, / some-action y este método requiere un POST, el bot puede intentar enviar un GET, lo que hará que aparezca este error. Sus registros web definitivamente podrían ayudar a confirmar si este fuera el caso. Incluso vemos a googlebot haciendo esto.
jakejgordon
Tengo este mismo error solo en el servidor Live (IIS 7.5). La implementación funciona bien en mi máquina de desarrollo, así como en otra máquina de soporte. agregar estos verbos y eliminar HttpGet no solucionó el problema. Cualquier otra sugerencia, por favor.
bjan
Como alternativa a denegar las solicitudes HEAD entrantes, es posible que desee entregar una respuesta adecuada. Ver stackoverflow.com/a/3197128/12484
Jon Schneider
15

Tuvimos un problema similar, pero descubrimos que estaba sucediendo porque un usuario estaba publicando en un controlador después de que se agotó el tiempo de inicio de sesión. A continuación, el sistema se redirige a la pantalla de inicio de sesión. Después de iniciar sesión, se redirigió a la URL en la que el usuario intentaba publicar, pero esta vez estaba haciendo una solicitud GET y, por lo tanto, no encontró la acción que estaba marcada con un atributo [HttpPost].

Johann Strydom
fuente
Mi solución actual es, en la medida de lo posible, hacer siempre un redireccionamiento a la acción Index al final de una acción. Lo siento por la respuesta tardía.
Johann Strydom
7

Tengo el mismo problema en asp.net mvc. este error - 404 no encontrado. Resuelvo el problema de esta manera: ponga este código en 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
fuente
6

Simplemente tuvimos el mismo problema en nuestra aplicación y pude rastrearlo hasta un problema de javascript / jquery. Tenemos enlaces en nuestra aplicación definidos usando Html.ActionLink () que luego son reemplazados en POST por jquery.

Primero habíamos definido el enlace:

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

Más tarde, anulamos la acción predeterminada con nuestra función SomePostEventHandler:

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

Esto estaba afectando a nuestra acción MVC que tenía un filtro HttpPost:

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

Lo que encontramos es que la mayoría de las veces esto funcionó muy bien. Sin embargo, en algunas cargas de página lentas (o usuarios realmente rápidos), el usuario hacía clic en el enlace antes de que se activara el evento jquery $ (document) .ready (), lo que significa que intentaban GET / Controller / SomeAction / XX en lugar de destino.

No queremos que el usuario OBTENGA esa URL, por lo que eliminar el filtro no es una opción para nosotros. En su lugar, simplemente conectamos el evento onclick del enlace de acción directamente (tuvimos que cambiar SomePostEventHandler () ligeramente para que esto funcione):

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

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

Entonces, la moraleja de la historia, al menos para nosotros, es que si está viendo estos errores, busque la URL que PIENSA que está PUBLICANDO y asegúrese de que lo está.

jslatts
fuente
2

Yo también tuve este problema.

En mi caso, estaba relacionado con restricciones de verbos en la acción solicitada, donde la vista era una, POSTpero la vista parcial se solicitaba dentro de admitida GETy HEADúnica. Agregar el POSTverbo a AcceptVerbsAttribute(en MVC 1.0) resolvió el problema.

Wolfyuk
fuente
2

A partir de los registros de IIS, nuestro problema fue causado por el robot de Google que intentó POST y GET para una acción de controlador solo POST.

Para este caso recomiendo manejar el 404 como la sugerencia de Dmitriy.

Enfocar
fuente
1

La respuesta aceptada actualmente funciona como se esperaba, pero no es el caso de uso principal de la función. En su lugar, utilice la función definida por ASP.NET. En mi caso, negué todo menos OBTENER y PUBLICAR:

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

Con el fragmento de código anterior, MVC devolverá correctamente un 404

Valchris
fuente
0

No debería ser

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

Además, ¿qué hacen sus filtros? ¿No pueden ocultar la acción, como ActionMethodSelectorAttribute?

queen3
fuente
Eso es un error de edición. Estaba tratando de proteger a los inocentes.
Chris Schoon
Completan algunos de los parámetros. Por ejemplo, UserIdFilter es un ayudante para obtener la identificación de usuario de la sesión / cookie / etc. Completa el primer parámetro. Editaré la publicación para incluirla.
Chris Schoon
0

Tengo un problema similar con la carga de archivos qq

Cuando la acción de publicación es /Document/Save, obtengo la excepción. No se encontró un método de acción pública 'Guardar' en el controlador 'Project.Controllers.DocumentController'.

Pero si la acción de publicación es /Document/Save/, ¡la publicación es correcta y funciona!

Dios salve el / ?

Tuizi
fuente
0

Mi causa raíz fue similar a la mencionada en el comentario.

Yo era ajaxSubmittingun formulario con el clic de un botón. Uno de los campos del formulario era de tipo Date. Sin embargo, debido a la diferencia en los formatos de fecha entre el cliente y la máquina del servidor, no ejecutó el método POST en el controlador. El servidor envió una 302respuesta y luego envió una GETsolicitud para el mismo método nuevamente.

Sin embargo, la acción en el controlador estaba decorada con el HttpPostatributo y, por lo tanto, no pudo encontrar el método y envió una 404respuesta.

Acabo de arreglar el código de modo que la falta de coincidencia en los formatos de fecha no causara un error y el problema se solucionó.

mridula
fuente
0

Elimina los [HttpGet]atributos y funcionará :)

Cătălin Rădoi
fuente
Si bien esto "resuelve" los errores, lo más probable es que usted (o alguien antes que usted) ponga esos [HttpGet]atributos allí a propósito, para evitar que las acciones sean invocadas a través de otros VERBOS
Nick Orlando
0

Para cualquiera que tenga este problema con angularjs, MVC y las inserciones de tipo {{imagepath}} en los atributos de image src, por ejemplo:

"No se encontró un método de acción pública '{{imagepath}} previous.png' en el controlador"

La solución es usar ng-src en lugar de src.

Espero que esto ayude a alguien :)

davaus
fuente
casi un año después, estaba buscando esto :) tnx!
Verthosa
0

Vea si simplemente navegar a la URL en cuestión es suficiente para reproducir el error. Lo sería si la acción solo se definiera como una acción POST. Hacer esto le permite reproducir el error a voluntad.

En cualquier caso, puede manejar globalmente el error como se muestra a continuación. Otra respuesta aquí que las referencias HandleUnknownActionsolo manejan URL con nombres de acción incorrectos, no nombres de controlador incorrectos. El siguiente enfoque maneja ambos.

Agregue esto a su controlador base (ver código omitido aquí):

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

Agregue un controlador de excepción global a Global.asax.cs que llame al método anterior o haga cualquier otra cosa que desee hacer con el error 404 detectado:

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
fuente