OnException

时间:2016-04-11 21:44:14

标签: asp.net-mvc

我创建了一个自定义属性,继承自HandleErrorAttribute:

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        try
        {
            Utility.LogAndNotifyOfError(filterContext.Exception, null, true);
        }
        catch(Exception ex)
        {
            filterContext.Exception = ex;
        }
    }
}

,然后注册:

filters.Add(new CustomHandleErrorAttribute());

这一直是按预期工作的。但是,我的日志方法的一个常见问题是它在写入事件日志时使用自定义事件日志源,而应用程序池帐户通常没有创建权限。创建事件日志源是一个简单的PowerShell脚本,但是我想在错误中实际包含这些消息:

        try
        {
            log.WriteEntry(error, EventLogEntryType.Error);
        }
        catch(SecurityException ex1)
        {
            throw new ErrorHandlerException($"The event log could not be written to due to a SecurityExcption.  The likely issue is that the '{eventLogSource}' does not already exist.  Please run the following powershell command:\r\n"
                + $"New - EventLog - LogName Application - Source {eventLogSource}", ex1);
        }

问题是OnException中的catch永远不会被命中。在调试时,我从LogAndNotifyOfError抛出的自定义错误会触发对OnException的第二次调用,并且从未看到我的ErrorHandlerException的详细信息。我希望asp.net错误页面出现在我的自定义错误详细信息中,而不是最初引发的SecurityException。

您甚至可以在显示的错误中看到周围的尝试: screenshot

编辑:列出的整个日志方法:

public static void LogAndNotifyOfError(Exception ex, String extraInfo, Boolean sendEmail)
{
    //if the error handler itself faulted...
    if (ex is ErrorHandlerException)
        return;

    string eventLogName = "Application";
    string eventLogSource = "MySourceName";

    String error = ex.ToString();
    if (error.Length > 28000)
        error.Substring(0, 28000);//event log is limited to 32k
    error += "\r\n\r\nAdditional Information: \r\n"
        + "Machine Name: " + Environment.MachineName + "\r\n"
        + "Logged in user:" + App.CurrentSecurityContext.CurrentUser?.UserId + "\r\n"
        + extraInfo + "\r\n";

    EventLog log = new EventLog(eventLogName);
    log.Source = eventLogSource;
    try
    {
        log.WriteEntry(error, EventLogEntryType.Error);
    }
    catch(SecurityException ex1)
    {//this doesn't work - for some reason, OnError still reports the original error.
        throw new ErrorHandlerException($"The event log could not be written to due to a SecurityExcption.  The likely issue is that the '{eventLogSource}' does not already exist.  Please run the following powershell command:\r\n"
            + $"New - EventLog - LogName Application - Source {eventLogSource}", ex1);
    }
    //if the email-to field has been set...
    if (!String.IsNullOrEmpty(App.Config.General.ErrorHandlerSendToAddresses) && sendEmail)
    {
        //...then send the email
        MailMessage email = new MailMessage();
        email.To.Add(App.Config.General.ErrorHandlerSendToAddresses);
        email.IsBodyHtml = false;

        email.Subject = String.Format("Error in {0}", eventLogSource);

        email.Body = email.Subject + "\r\n\r\n"
            //+ "Note: This error may be occuring continuously, but this email is only sent once per hour, per url, in order to avoid filling your mailbox.  Please check the event log for reoccurances and variations of this error.\r\n\r\n"
            + "The error description is as follows: \r\n\r\n"
            + error + "\r\n\r\n";

        SmtpClient smtp = new SmtpClient();
        smtp.Send(email);
    }
}

1 个答案:

答案 0 :(得分:0)

我想通了(有点)。看起来当新抛出的异常有一个内部异常时,它只显示那个内部异常。外部或内部异常的类型无关紧要。