我可以在Elmah过滤器中获得所需的路线吗?

时间:2014-07-25 10:38:04

标签: asp.net-mvc elmah

在我的ASP.NET MVC应用程序中,我有一个非常具体的操作,我不想让Elmah处理,因为它可以发出500响应状态代码作为其正常功能的一部分。

我不希望被此路由中发生的错误发送垃圾邮件,但我也不想在其他任何地方关闭Elmah记录500个错误。

有没有办法在web.config中以声明方式执行此操作,还是必须编写自己的Assertion? 或者,重新说一下,有没有办法在测试断言中获得带有绑定的路由?

PS:对于那些想知道为什么我会允许我的行为生成500的人,这是因为它是客户定义代码的包装器,我希望我的客户立即知道他们的自定义代码是否有错误。

1 个答案:

答案 0 :(得分:2)

看起来你正在让那个特定的动作引发未处理的异常。我想是的,因为如果你只是返回500错误代码而没有例外,Elmah没有记录它:

public ActionResult ThrowError()
{
    //your wrapper calling customer code        

    return new HttpStatusCodeResult(500, "Buggy code");
}

所以我假设您的操作是抛出未处理的异常(可能因此您的客户可以看到异常详细信息?)。假设您的操作方法位于HomeController,如下所示:

public ActionResult ThrowError()
{    
    //your wrapper calling customer code
    // the customer code throws an exception: 
    throw new Exception("Buggy code");
}

每次你去/Home/ThrowError,你都会得到一个未处理的异常,结果是500,并由Elmah记录。所以你需要从Elmah过滤掉它,它会给你the following options

您可以在global.asax上为Elmah添加以下过滤器,告诉Elmah忽略该特定网址上的例外情况:

void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e)
{
    var httpContext = HttpContext.Current;
    if(httpContext == null) return;

    if (httpContext.Request.Url.AbsolutePath == "/home/throwerror") e.Dismiss();
}

如果您已启用ErrorFilter模块,则可以在web.config中执行相同操作:

<system.web>
  <httpModules>
    <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
  </httpModules>
</system.web>

<system.webServer>
  <modules>
    <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
  </modules>
</system.webServer>

<elmah>
    <errorFilter>
      <test>
        <and>
          <equal binding="Context.Request.ServerVariables['URL']" value="/home/throwerror" type="String" />
          <!--You could also use a regex for the url-->
          <!--<regex binding="Context.Request.ServerVariables['URL']"
                  pattern="/home/throwerror\d*" />-->
        </and>
      </test>
    </errorFilter>
</elmah>

我真的不喜欢这种方法,它取决于列出你想要过滤异常的所有网址(或者确保所有这些网址遵循你可以在正则表达式上表达的模式)。如果您可以将从客户代码抛出的异常包装到特定异常中,则可以过滤掉该类型的所有未处理异常,无论它们是从哪个URL中抛出。

因此,您可以创建一个新的异常类型并在代码包装客户代码中使用它:

public class CustomerException : Exception
{
    public CustomerException(Exception e)
        : base(e.Message, e)
    {
    }
}

public ActionResult ThrowError()
{
    try
    {
        //your wrapper calling customer code
        // the customer code throws an exception: 
        throw new Exception("Buggy code");
    }
    catch (Exception e)
    {
        throw new CustomerException(e);
    }
}

现在,您可以在global.asaxweb.config中过滤掉Elmah中的这些例外:

void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e)
{
    var httpContext = HttpContext.Current;
    if(httpContext == null) return;

    if (e.Exception is CustomerException) e.Dismiss();
}

<errorFilter>
  <test>
    <jscript>
      <expression>
        <![CDATA[
        // @assembly mscorlib
        // @assembly WebApplication3
        // @import WebApplication3.Controllers

        // In my dummy project, CustomerException is located in WebApplication3.Controllers
        $.Exception instanceof CustomerException
        ]]>
      </expression>
    </jscript>
  </test>
</errorFilter> 

现在使用最后一种方法,你不依赖于动作网址。

希望这有帮助!