C# ELMAH异常生成泛型;“服务不可用”;消息

C# ELMAH异常生成泛型;“服务不可用”;消息,c#,asp.net,asp.net-mvc,elmah,elmah.mvc,C#,Asp.net,Asp.net Mvc,Elmah,Elmah.mvc,我正在尝试创建一个可用性页面,该页面检查站点使用的所有服务,将每个检查包装为try/catch,然后向用户显示任何失败。其中一个服务是ELMAH,所以我打电话给它是为了再次检查我们是否可以成功地在那里记录错误 控制器: 当艾玛成功时,一切都很好。当它抛出任何类型的错误(DB权限等)时,我会得到一个try/catch或任何正常错误捕获部件都无法捕获的错误:ASP.NET MVCHandleError,customErrors重定向,甚至system.webServer中的httpErrors。显示

我正在尝试创建一个可用性页面,该页面检查站点使用的所有服务,将每个检查包装为try/catch,然后向用户显示任何失败。其中一个服务是ELMAH,所以我打电话给它是为了再次检查我们是否可以成功地在那里记录错误

控制器: 当艾玛成功时,一切都很好。当它抛出任何类型的错误(DB权限等)时,我会得到一个try/catch或任何正常错误捕获部件都无法捕获的错误:ASP.NET MVC
HandleError
customErrors
重定向,甚至
system.webServer
中的
httpErrors
。显示的不是正常的IIS通用消息,而是一行“服务不可用”

答复: 就这样。至少我知道我的可用性不起作用,但我想至少向用户显示是ELMAH造成了问题,并显示它试图使用的连接字符串。所以,我需要以某种方式捕捉这个异常

我尝试了多种不同的方式来调整我的web.config,但我怀疑ELMAH将自己插入模块管道的方式会阻止我处理这个问题

编辑: 为了澄清,这是一个简化的示例。我不打算向最终用户公开这些信息。此可用性页面仅对正在解决未来问题的内部用户可用


ELMAH只是所讨论的应用程序使用的服务/数据库之一,我想为管理员提供一个类似于仪表板的快速视图,以了解上下情况。如果ELMAH错误导致此insta-503,我不能这样做。

不,不从不向用户显示连接字符串,从不告诉他们问题所在。这样做是一个严重的安全漏洞。简单地说,不要这样做。用Elmah解决您潜在的问题


错误处理管道中的问题非常糟糕,因为它会导致它尝试处理生成的新错误,这基本上会导致循环。ASP.NET引擎识别出一些严重的错误,因此它给出了一个通用的“服务不可用”消息。检查服务器上的事件日志,找出潜在的Elmah错误并进行更正。

好的,如果没有任何代码,这基本上是不可能的。Elmah中的
Raise
方法不会让您看到任何错误,除非您跟踪它:

// ErrorLogModule.LogException
try
{
    Error error = new Error(e, context);
    ErrorLog errorLog = this.GetErrorLog(context);
    error.ApplicationName = errorLog.ApplicationName;
    string id = errorLog.Log(error);
    errorLogEntry = new ErrorLogEntry(errorLog, id, error);
}
catch (Exception value)
{
    Trace.WriteLine(value);
}
但是,当成功记录事件时,ErrorLogModule将调用
logged
事件,以便让潜在的侦听器知道记录成功。因此,让我们快速编写一个自定义类,该类将覆盖ErrorLogModule中的一些方法,并允许我们注意到事件是记录的:

public class CustomErrorLogModule: Elmah.ErrorLogModule
{
    public Boolean SomethingWasLogged { get; set; }
    protected override void OnLogged(Elmah.ErrorLoggedEventArgs args)
    {
        SomethingWasLogged = true;
        base.OnLogged(args);
    }

    protected override void LogException(Exception e, HttpContext context)
    {
        SomethingWasLogged = false;
        base.LogException(e, context);
        if (!SomethingWasLogged)
        {
            throw new InvalidOperationException("An error was not logged");
        }
    }
}
将配置文件中的
ErrorLogModule
CustomErrorLogModule
交换,Elmah会在发生错误时投诉;调用
Elmah.ErrorSignal.FromCurrentContext().Raise(新异常(“测试”))允许调用中抛出
InvalidOperationException(“未记录错误”)


如果您想获取在尝试记录异常时发生的确切异常,可以使用ErrorLogModule在异常发生时跟踪异常这一事实。创建侦听器类:

public class ExceptionInterceptor : DefaultTraceListener
{
    public Exception TracedException { get; set; }
    public override void WriteLine(object o)
    {
        var exception = o as Exception;
        if (exception != null)
        {
            TracedException = exception;
        }
    }
}
然后您的
LogException
方法变为

protected override void LogException(Exception e, HttpContext context)
{
    var exceptionListener = new ExceptionInterceptor();
    Trace.Listeners.Add(exceptionListener);
    try
    {
        SomethingWasLogged = false;
        base.LogException(e, context);
        if (!SomethingWasLogged)
        {
            throw exceptionListener.TracedException;
        }
    }
    finally
    {
        Trace.Listeners.Remove(exceptionListener);
    }
}
编辑:或者即使你想尽量简洁

public class ExceptionInterceptor : DefaultTraceListener
{
    public override void WriteLine(object o)
    {
        var exception = o as Exception;
        if (exception != null)
        {
            throw exception;
        }
    }
}

// snip... LogException in your CustomErrorLogModule
protected override void LogException(Exception e, HttpContext context)
{
    var exceptionListener = new ExceptionInterceptor();
    Trace.Listeners.Add(exceptionListener);
    try
    {
        base.LogException(e, context);
    }
    finally
    {
        Trace.Listeners.Remove(exceptionListener);
    }
}

最后一句话:这种检查服务可用性的方式有一种气味,您将在错误数据库中添加测试异常,这可能不是您想要的行为。我知道您的目标是检查整个日志记录链,但也许有其他方法可以做到这一点;我真的不知道你的背景,所以我不会再评论了,但请不要犹豫,仔细想想

无论如何,这些更改应该允许您接收所需的异常



重要编辑:非常重要的一点:您可能希望在
CustomErrorLogModule
中添加一个触发器,以便在不测试时它不会抛出。您在Elmah中观察到的弹性通常是一件好事,因为您不希望诊断平台导致可能需要其他诊断的问题。这就是为什么Elmah或日志框架不会抛出异常,这就是为什么您应该使异常重新触发机制可触发,这样您的程序在Elmah中引发异常时就不必关注其步骤。

您误解了。我正在使用其他身份验证机制阻止实际用户访问,但其受众是需要检查站点的内部用户。我的问题是,当ELMAH以某种方式出现故障时,我希望内部用户能够快速看到有用的错误。解决底层ELMAH错误是可能的,但我想捕获它。“服务不可用”不会引发异常。这是一个IIS错误,而不是ASP.NET错误。我觉得这令人沮丧,并且觉得IIS到.NET管道体系结构中存在疏忽。这里更好的问题是,为什么Elmah(不是独立的服务,而是应用程序的服务)返回此错误。我会期待更多。。。我找不到任何关于Elmah失败时会发生什么的文档,但我使用Elmah手动记录异常,我不记得遇到过这个问题……是的!回答得很好,谢谢你提供的详细信息。是的,我只想在测试时触发投掷。当然,我同意测试异常有一种气味,但这总比不知道我们的异常是什么时候完全没有被记录要好。非常感谢你。
protected override void LogException(Exception e, HttpContext context)
{
    var exceptionListener = new ExceptionInterceptor();
    Trace.Listeners.Add(exceptionListener);
    try
    {
        SomethingWasLogged = false;
        base.LogException(e, context);
        if (!SomethingWasLogged)
        {
            throw exceptionListener.TracedException;
        }
    }
    finally
    {
        Trace.Listeners.Remove(exceptionListener);
    }
}
public class ExceptionInterceptor : DefaultTraceListener
{
    public override void WriteLine(object o)
    {
        var exception = o as Exception;
        if (exception != null)
        {
            throw exception;
        }
    }
}

// snip... LogException in your CustomErrorLogModule
protected override void LogException(Exception e, HttpContext context)
{
    var exceptionListener = new ExceptionInterceptor();
    Trace.Listeners.Add(exceptionListener);
    try
    {
        base.LogException(e, context);
    }
    finally
    {
        Trace.Listeners.Remove(exceptionListener);
    }
}