I am attempting to configure ELMAH to filter 404 errors and I am running into difficulties with the XML-provided filter rules in my Web.config file. I followed the tutorial here and here and added an <is-type binding="BaseException" type="System.IO.FileNotFoundException" />
declaration under my <test><or>...
declaration, but that completely failed.
When I tested it locally I stuck a breakpoint in void ErrorLog_Filtering() {}
of the Global.asax and found that the System.Web.HttpException
that gets fired by ASP.NET for a 404 doesn't seem to have a base type of System.IO.FileNotFound
, but rather it is simply a System.Web.HttpException
. I tested this by calling e.Exception.GetBaseException().GetType()
in the event handler.
Next I decided to try a <regex binding="BaseException.Message" pattern="The file '/[^']+' does not exist" />
in the hopes that any exception message matching the pattern "The file '/foo.ext' does not exist" would get filtered, but that too is having no effect. As a last resort I tried <is-type binding="BaseException" type="System.Exception" />
, and even that is entirely disregarded.
I'm inclined to think there's a configuration error with ELMAH, but I fail to see any. Am I missing something blatantly obvious?
Here's the relevant stuff from my web.config:
<configuration>
<configSections>
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/>
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah"/>
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections>
<elmah>
<errorFilter>
<test>
<or>
<equal binding="HttpStatusCode" value="404" type="Int32" />
<regex binding="BaseException.Message" pattern="The file '/[^']+' does not exist" />
</or>
</test>
</errorFilter>
<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data/logs/elmah" />
</elmah>
<system.web>
<httpModules>
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
</modules>
</system.webServer>
</configuration>
It was indeed a configuration error, just not one that was particularly obvious.
The order in which the ELMAH HttpModules are registered is a pertinent concern because in order for ELMAH to filter the exception it must first know which modules will be consuming the exception. The ErrorFilter HttpModule must be registered last to prevent the other modules from processing the exception being filtered. This seems [kind of] backwards to me, but at least it works.
<configuration>
...
<system.web>
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
</modules>
</system.webServer>
</configuration>
After reviewing the ELMAH Wiki entry on ErrorFiltering again I discovered this little tidbit of information which really deserves a <strong /> tag, if you ask me. (Edit: They've bolded it since I first answered this question; props!)
The first step is to configure an additional module called Elmah.ErrorFilterModule. Make sure you add it after any of the logging modules from ELMAH, as shown here with ErrorLogModule: