ASP.NET MVC 404 Manejo de errores [duplicado]


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

He realizado los cambios descritos en 404 Http error handler en Asp.Net MVC (RC 5) y todavía estoy recibiendo la página de error estándar 404. ¿Necesito cambiar algo en IIS?

Author: Community, 2009-04-04

6 answers

Otra solución.

Agregue ErrorController o página estática con información de error 404.

Modifica tu web.config (en el caso del controlador).

<system.web>
    <customErrors mode="On" >
       <error statusCode="404" redirect="~/Errors/Error404" />
    </customErrors>
</system.web>

O en caso de página estática

<system.web>
    <customErrors mode="On" >
        <error statusCode="404" redirect="~/Static404.html" />
    </customErrors>
</system.web>

Esto manejará tanto las rutas perdidas como las acciones perdidas.

 136
Author: Mike Chaliy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-25 23:50:05

He investigado MUCHO sobre cómo administrar correctamente 404s en MVC (específicamente MVC3) , y esta, IMHO es la mejor solución que se me ha ocurrido: {[14]]}

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

(Optativo)

Explicación:

Hay 6 escenarios que puedo pensar en donde un ASP.NET Las aplicaciones MVC3 pueden generar 404s.

Generado por ASP.NET:

  • Escenario 1: La 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 existir.

Generado manualmente:

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

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

  • Escenario 6: Una acción modifica manualmente la Respuesta.statusCode propiedad a 404.

Objetivos

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

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

  • (C) Enviar la respuesta directamente, sin involucrar una redirección 302.

Intento de Solución: Errores personalizados

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>

Problemas con esta solución:

  • No cumple el objetivo (A) en escenarios (1), (4), (6).
  • No cumple con objetivo (B) automáticamente. Debe programarse manualmente.
  • No cumple el objetivo C).

Intento de solución: Errores HTTP

<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

Problemas con esta solución:

  • Solo funciona en IIS 7+.
  • No cumple el objetivo (A) en escenarios (2), (3), (5).
  • No cumple automáticamente el objetivo B). Debe programarse manualmente.

Intento de Solución: Errores HTTP con Sustitúyase

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

Problemas con esta solución:

  • Solo funciona en IIS 7+.
  • No cumple automáticamente el objetivo B). Debe programarse manualmente.
  • Oculta las excepciones http a nivel de aplicación. Por ejemplo, no se puede usar la sección customErrors, System.Web.Mvc.Tributo al terrorista manual, etc. No solo puede mostrar páginas de error genéricas.

Solución Intento customErrors y HTTP Errores

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>

Y

<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

Problemas con esta solución:

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

Las personas que han tenido problemas con esto antes incluso 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.

 353
Author: Marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-18 15:27:55

La respuesta de Marco es la MEJOR solución. Necesitaba controlar mi manejo de errores, y quiero decir realmente controlarlo. Por supuesto, he ampliado un poco la solución y he creado un sistema de gestión de errores completo que administra 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 basada en Controlador personalizado que he creado. El Controlador Base Personalizado fue creado para anular el manejo de errores. Aquí está mi clase de Controlador Base personalizada:

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á utilizando un Modelo basado en ExceptionContext

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

 5
Author: Yousi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-11 13:03:02

Parece que esta es la mejor manera de atrapar todo.

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

 4
Author: Clearly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:31

Lo que puedo recomendar es buscar en FilterAttribute. Por ejemplo MVC ya tiene HandleErrorAttribute. Puede personalizarlo para manejar solo 404. Responder si usted está interesado voy a mirar ejemplo.

BTW

La solución(con la última ruta) que ha aceptado en la pregunta anterior no funciona en muchas de las situaciones. La segunda solución con HandleUnknownAction funcionará pero requerirá hacer este cambio en cada controlador o tener un solo controlador base.

Mi choice es una solución con HandleUnknownAction.

 1
Author: Mike Chaliy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-05 15:28:20

En IIS, puede especificar una redirección a "cierta" página basada en el código de error. En su ejemplo, puede configurar 404 - > Su página de error 404 personalizada.

 0
Author: J.W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-04 19:33:16