51 votos

Asp.net mvc override OnException en el controlador base sigue propagando a Application_Error

Estoy tratando de devolver una vista que no emita una redirección al usuario basada en ciertos errores que podrían ocurrir desde mi aplicación, quiero manejar los errores + registrarlos dentro de mi controlador base, no quiero que el error se propague hasta mi método Global.asax - Application_Error() ya que quiero que este método maneje cualquier otro error dentro de mi aplicación, por ejemplo, el usuario ingresa una URL falsa, ¿alguien ha encontrado una manera de evitar esto?

NOTA: He dejado mi código comentado ya que tenía una solución para algunos problemas, esto también muestra que tengo múltiples excepciones para manejar posibles...

EDIT: Si emito una RedirectToAction dentro de este override OnException todo funciona como se espera, pero sólo quiero devolver la vista y ninguna redirección...

Mi método de controlador base es:

    protected override void OnException(ExceptionContext filterContext)
    {
        //dont interfere if the exception is already handled
        if (filterContext.ExceptionHandled)
            return;

        //let the next request know what went wrong
        filterContext.Controller.TempData["exception"] = filterContext.Exception;

        //log exception
        _logging.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(filterContext.Exception));

        //set up redirect to my global error handler
        //if (filterContext.Exception.GetType() == typeof(NoAccessException))
        //    filterContext.Result = View(new RouteValueDictionary
        //    (new { area = "", controller = "Error", action = "PublicError" }));

        //else {
        //Only return view, no need for redirection
        filterContext.Result = View(new RouteValueDictionary
        (new { area = "", controller = "Error", action = "NoAccess" }));
        //}
        //advise subsequent exception filters not to interfere and stop
        // asp.net from showing yellow screen of death
        filterContext.ExceptionHandled = true;

        //erase any output already generated
        filterContext.HttpContext.Response.Clear();

        //base.OnException(filterContext);
    }

Este método debe manejar cualquier otro error que pueda aparecer en mi aplicación, no quiero que los errores anteriores sean manejados dentro de mi Application_Error()

protected void Application_Error()
        {

            Exception exception = Server.GetLastError();
            // Log the exception.

            var logger = Container.Get<ILoggingService>();
            logger.Error(User.Identity.Name, ExceptionHelper.BuildWebExceptionMessage(exception));

            Response.Clear();

            HttpException httpException = exception as HttpException;

            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");

            //if (httpException == null)
            //{
            routeData.Values.Add("action", "PublicError");
            //}
            //else //It's an Http Exception, Let's handle it.
            //{
            //    switch (httpException.GetHttpCode())
            //    {
            //        case 404:
            //            // Page not found.
            //            routeData.Values.Add("action", "HttpError404");
            //            break;
            //        case 500:
            //            // Server error.
            //            routeData.Values.Add("action", "HttpError500");
            //            break;

            //        // Here you can handle Views to other error codes.
            //        // I choose a General error template  
            //        default:
            //            routeData.Values.Add("action", "General");
            //            break;
            //    }
            //}

            // Pass exception details to the target error View.
            routeData.Values.Add("error", exception);

            // Clear the error on server.
            Server.ClearError();

            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;

            // Call target Controller and pass the routeData.
            IController errorController = new ErrorController();
            errorController.Execute(new RequestContext(
                 new HttpContextWrapper(Context), routeData));
        }

75voto

Darin Dimitrov Puntos 528142

Lo siguiente debería funcionar:

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
    {
        return;
    }
    filterContext.Result = new ViewResult
    {
        ViewName = "~/Views/Shared/Error.aspx"
    };
    filterContext.ExceptionHandled = true;
}

Asegúrese también de que no se lanza ninguna excepción en este método o se propagará a Application_Error .

0 votos

¿Se quedaría la URL como estaba originalmente? Eso es lo que intento conseguir con el método anterior, es decir, que si se produce un error se devuelva la vista correspondiente y la url siga siendo la misma/la url no cambie...

1 votos

@Haroon, sí absolutamente, seguirá siendo lo mismo. Será la url inicial que causó la excepción, excepto que en lugar de una Pantalla Amarilla de la Muerte se renderizará la vista personalizada.

1 votos

Puede ser que mi pregunta sea tonta... pero puede alguien decirme donde esta OnException() (el código de arriba) debe ser colocado en la aplicación. En cualquier controller clase o en global.ascx.cs . ¿Dónde?

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X