asp.net-mvc - page - onexception mvc
Errores de registro en ASP.NET MVC (6)
¿Has pensado en extender el atributo HandleError? Además, Scott tiene una buena publicación en el blog sobre interceptores de filtros en controladores / acciones here .
Actualmente estoy usando log4net en mi aplicación ASP.NET MVC para registrar excepciones. La forma en que lo estoy haciendo es que todos mis controladores hereden de una clase BaseController. En el evento OnActionExecuting de BaseController, registro cualquier excepción que pueda haber ocurrido:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Log any exceptions
ILog log = LogManager.GetLogger(filterContext.Controller.GetType());
if (filterContext.Exception != null)
{
log.Error("Unhandled exception: " + filterContext.Exception.Message +
". Stack trace: " + filterContext.Exception.StackTrace,
filterContext.Exception);
}
}
Esto funciona muy bien si se produjo una excepción no controlada durante una acción del controlador.
En cuanto a los errores 404, tengo un error personalizado configurado en mi web.config así:
<customErrors mode="On">
<error statusCode="404" redirect="~/page-not-found"/>
</customErrors>
Y en la acción del controlador que maneja la url "page-not-found", registro la url original solicitada:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult PageNotFound()
{
log.Warn("404 page not found - " + Utils.SafeString(Request.QueryString["aspxerrorpath"]));
return View();
}
Y esto también funciona.
El problema que estoy teniendo es cómo registrar errores que están en las páginas .aspx. Digamos que tengo un error de compilación en una de las páginas o un código en línea que lanzará una excepción:
<% ThisIsNotAValidFunction(); %>
<% throw new Exception("help!"); %>
Parece que el atributo HandleError está reencaminando esto correctamente a mi página Error.aspx en la carpeta compartida, pero definitivamente no está siendo capturado por el método OnActionExecuted de mi BaseController. Pensaba que podría poner el código de registro en la página Error.aspx, pero no estoy seguro de cómo recuperar la información de error en ese nivel.
Consideraría simplificar su aplicación web conectando Elmah .
Agrega el ensamblaje Elmah a su proyecto y luego configura su web.config. A continuación, registrará las excepciones creadas en el controlador o en el nivel de la página. Se puede configurar para iniciar sesión en varios lugares diferentes (como SQL Server, correo electrónico, etc.). También proporciona una interfaz web, para que pueda navegar a través del registro de excepciones.
Es lo primero que agrego a cualquier aplicación asp.net mvc que creo.
Todavía uso log4net, pero tiendo a usarlo para registrar depuración / información, y dejar todas las excepciones a Elmah.
También puede encontrar más información en la pregunta ¿Cómo registra errores (Excepciones) en sus aplicaciones ASP.NET? .
La vista Error.aspx se define así:
namespace MvcApplication1.Views.Shared
{
public partial class Error : ViewPage<HandleErrorInfo>
{
}
}
HandleErrorInfo tiene tres propiedades: string ActionName string ControllerName Exception Exception
Debería poder acceder a HandleErrorInfo y, por lo tanto, a la Excepción dentro de la vista.
MVC3
Crear atributo que hereda de HandleErrorInfoAttribute e incluye su elección de registro
public class ErrorLoggerAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
LogError(filterContext);
base.OnException(filterContext);
}
public void LogError(ExceptionContext filterContext)
{
// You could use any logging approach here
StringBuilder builder = new StringBuilder();
builder
.AppendLine("----------")
.AppendLine(DateTime.Now.ToString())
.AppendFormat("Source:/t{0}", filterContext.Exception.Source)
.AppendLine()
.AppendFormat("Target:/t{0}", filterContext.Exception.TargetSite)
.AppendLine()
.AppendFormat("Type:/t{0}", filterContext.Exception.GetType().Name)
.AppendLine()
.AppendFormat("Message:/t{0}", filterContext.Exception.Message)
.AppendLine()
.AppendFormat("Stack:/t{0}", filterContext.Exception.StackTrace)
.AppendLine();
string filePath = filterContext.HttpContext.Server.MapPath("~/App_Data/Error.log");
using(StreamWriter writer = File.AppendText(filePath))
{
writer.Write(builder.ToString());
writer.Flush();
}
}
Coloque el atributo en Global.asax RegisterGlobalFilters
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// filters.Add(new HandleErrorAttribute());
filters.Add(new ErrorLoggerAttribute());
}
Puede enganchar en el evento OnError en Global.asax.
Algo como esto:
/// <summary>
/// Handles the Error event of the Application control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Application_Error(object sender, EventArgs e)
{
if (Server != null)
{
Exception ex = Server.GetLastError();
if (Response.StatusCode != 404 )
{
Logging.Error("Caught in Global.asax", ex);
}
}
}
Puede intentar examinar HttpContext.Error, pero no estoy seguro de esto.