Manejo de errores ASP.NET MVC 404

Posible duplicado:
¿Cómo puedo manejar 404 correctamente en ASP.NET MVC?

Realicé los cambios delineados en el controlador de error 404 Http en Asp.Net MVC (RC 5) y sigo obteniendo la página de error 404 estándar. ¿Debo cambiar algo en IIS?

Otra solución más

Agregue los Controles de Error o la página estática a la información de error 404.

Modifique su web.config (en caso de controlador).

     

O en el caso de una página estática

      

Esto manejará las rutas perdidas y las acciones perdidas.

He investigado MUCHO sobre cómo administrar adecuadamente 404s en MVC (específicamente MVC3) , y esto, en mi humilde opinión, es la mejor solución que he encontrado:

En global.asax:

 public class MvcApplication : HttpApplication { protected void Application_EndRequest() { if (Context.Response.StatusCode == 404) { Response.Clear(); var rd = new RouteData(); rd.DataTokens["area"] = "AreaName"; // In case controller is in another area rd.Values["controller"] = "Errors"; rd.Values["action"] = "NotFound"; IController c = new ErrorsController(); c.Execute(new RequestContext(new HttpContextWrapper(Context), rd)); } } } 

ErrorsController:

 public sealed class ErrorsController : Controller { public ActionResult NotFound() { ActionResult result; object model = Request.Url.PathAndQuery; if (!Request.IsAjaxRequest()) result = View(model); else result = PartialView("_NotFound", model); return result; } } 

Editar:

Si está utilizando IoC (por ejemplo, AutoFac), debe crear su controlador usando:

 var rc = new RequestContext(new HttpContextWrapper(Context), rd); var c = ControllerBuilder.Current.GetControllerFactory().CreateController(rc, "Errors"); c.Execute(rc); 

En lugar de

 IController c = new ErrorsController(); c.Execute(new RequestContext(new HttpContextWrapper(Context), rd)); 

(Opcional)

Explicación:

Hay 6 escenarios en los que puedo pensar que una aplicación ASP.NET MVC3 puede generar 404s.

Generado por ASP.NET:

  • Escenario 1: URL no coincide con una ruta en la tabla de rutas.

Generado por ASP.NET MVC:

  • Escenario 2: URL coincide con una ruta, pero especifica un controlador que no existe.

  • Escenario 3: URL coincide con una ruta, pero especifica una acción que no existe.

Manualmente generado:

  • Escenario 4: una acción devuelve un HttpNotFoundResult utilizando el método HttpNotFound ().

  • Escenario 5: una acción arroja una HttpException con el código de estado 404.

  • Escenario 6: una acción modifica manualmente la propiedad Response.StatusCode a 404.

Objetivos

  • (A) Mostrar una página de error 404 personalizada para el usuario.

  • (B) Mantenga el código de estado 404 en la respuesta del cliente (especialmente importante para SEO).

  • (C) Envíe la respuesta directamente, sin incluir una redirección 302.

Intento de solución: errores personalizados

      

Problemas con esta solución:

  • No cumple con el objective (A) en los escenarios (1), (4), (6).
  • No cumple con el objective (B) automáticamente. Debe ser progtwigdo manualmente.
  • No cumple con el objective (C).

Intento de solución: errores de HTTP

       

Problemas con esta solución:

  • Solo funciona en IIS 7+.
  • No cumple con el objective (A) en los escenarios (2), (3), (5).
  • No cumple con el objective (B) automáticamente. Debe ser progtwigdo manualmente.

Intento de solución: Errores HTTP con Reemplazar

       

Problemas con esta solución:

  • Solo funciona en IIS 7+.
  • No cumple con el objective (B) automáticamente. Debe ser progtwigdo manualmente.
  • Oculta las excepciones http de nivel de aplicación. Por ejemplo, no puede usar la sección customErrors, System.Web.Mvc.HandleErrorAttribute, etc. No solo puede mostrar páginas de error genéricas.

Solución Intento de customErrors y errores de HTTP

      

y

       

Problemas con esta solución:

  • Solo funciona en IIS 7+.
  • No cumple con el objective (B) automáticamente. Debe ser progtwigdo manualmente.
  • No cumple con el objective (C) en los escenarios (2), (3), (5).

Las personas que han tenido problemas con esto incluso antes intentaron crear sus propias bibliotecas (ver http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html ). Pero la solución anterior parece cubrir todos los escenarios sin la complejidad de usar una biblioteca externa.

La respuesta de Marco es la MEJOR solución. Necesitaba controlar mi manejo de errores, y me refiero a realmente CONTROLARLO. Por supuesto, amplié un poco la solución y creé un sistema completo de administración de errores que maneja todo. También he leído sobre esta solución en otros blogs y parece muy aceptable para la mayoría de los desarrolladores avanzados.

Aquí está el código final que estoy usando:

 protected void Application_EndRequest() { if (Context.Response.StatusCode == 404) { var exception = Server.GetLastError(); var httpException = exception as HttpException; Response.Clear(); Server.ClearError(); var routeData = new RouteData(); routeData.Values["controller"] = "ErrorManager"; routeData.Values["action"] = "Fire404Error"; routeData.Values["exception"] = exception; Response.StatusCode = 500; if (httpException != null) { Response.StatusCode = httpException.GetHttpCode(); switch (Response.StatusCode) { case 404: routeData.Values["action"] = "Fire404Error"; break; } } // Avoid IIS7 getting in the middle Response.TrySkipIisCustomErrors = true; IController errormanagerController = new ErrorManagerController(); HttpContextWrapper wrapper = new HttpContextWrapper(Context); var rc = new RequestContext(wrapper, routeData); errormanagerController.Execute(rc); } } 

y dentro de mi ErrorManagerController:

  public void Fire404Error(HttpException exception) { //you can place any other error handling code here throw new PageNotFoundException("page or resource"); } 

Ahora, en mi acción, estoy lanzando una excepción personalizada que he creado. Y mi controlador está heredando de una clase personalizada basada en el controlador que he creado. El controlador base personalizado se creó para anular el manejo de errores. Aquí está mi clase personalizada de controlador de base:

 public class MyBasePageController : Controller { protected override void OnException(ExceptionContext filterContext) { filterContext.GetType(); filterContext.ExceptionHandled = true; this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext); base.OnException(filterContext); } } 

El “ErrorManager” en el código anterior es solo una vista que está usando un modelo basado en ExceptionContext

Mi solución funciona perfectamente y puedo manejar CUALQUIER error en mi sitio web y mostrar diferentes mensajes basados ​​en CUALQUIER tipo de excepción.

Parece que esta es la mejor manera de atrapar todo.

¿Cómo puedo manejar 404 correctamente en ASP.NET MVC?

Lo que puedo recomendar es buscar en FilterAttribute. Por ejemplo, MVC ya tiene HandleErrorAttribute. Puedes personalizarlo para que maneje solo 404. Responde si estás interesado veré un ejemplo.

Por cierto

La solución (con la última ruta) que ha aceptado en la pregunta anterior no funciona en la mayoría de las situaciones. La segunda solución con HandleUnknownAction funcionará, pero es necesario realizar este cambio en cada controlador o tener un solo controlador base.

Mi elección es una solución con HandleUnknownAction.

En IIS, puede especificar un redireccionamiento a la página “determinada” en función del código de error. En su ejemplo, puede configurar 404 -> Su página de error 404 personalizada.