ELMAH with ASP.NET MVC

We finally got to the point of needing some error reporting in our new application. We’d read about ELMAH before and assumed we’d use that, but that was a while before we decided to go with the ASP.NET MVC framework instead of the traditional WebForms.

I was a little worried we’d hit some road block using ELMAH in conjunction with ASP.NET MVC, but it actually works out of the box without a hitch. ELMAH has a built in module for displaying any logged errors, and is accessible (by default) via http://localhost/elmah.axd. The latest releases of ASP.NET MVC automatically ignore routes with a .axd extension, though I’m not sure for how many releases they’ve been including that, so earlier releases will have a problem getting to that URL.

Simone Busoli wrote up an excellent article on the most important features of ELMAH and getting it setup. A must read if you’re going to implement this solution.

Here’s a quick run-down of the steps we went through for our application, though (using SQL logging & emailing the developers whenever an exception is logged):

  1. Reference the ELMAH.dll assembly in your project.
  2. Define the section group in your web.config:
    <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" />
    </sectionGroup>
  3. Define the needed ELMAH section elements, along with their related SQL connection string, in your web.config (we’re only allowing access to the error page via the local host):
    <elmah>
        <security allowRemoteAccess="0" />
        <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ErrorLogging" />
        <errorMail
            from="PPError@PatriotSoftware.com"
            to="PPDevs@SynergyDataSystems.com"
            subject="Patriot Pay Error"
            async="true"
            smtpPort="25"
            smtpServer="imail.topechelon.corp" />
    </elmah>
     
    <connectionStrings>
        <add name="ErrorLogging" connectionString="Data Source=...." />
    </connectionStrings>
  4. Add the follow handler to the section that’ll allow you to view the errors (I used the path errors.axd instead of the default elmah.axd, just because I hate using default URL like that in case we ever allow this on something other than localhost w/a restricted login):
    <add verb="POST,GET,HEAD" path="errors.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
  5. Add the following modules to the section, which will actually catch exceptions for logging to SQL and emailing out:
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
  6. (Optional) Add the following methods to your Global.asax, which will filter all exceptions thrown on the local host and ignore them (so developing on your local machine won’t keep emailing everyone else, which, trust me, gets old pretty damn quick):
    public void errorLog_Filtering(object sender, ExceptionFilterEventArgs e)
    {
        if(ErrorFiltering.Filter(new HttpContextWrapper(e.Context)))
        {
            e.Dismiss();
        }
    }
     
    public void errorMail_Filtering(object sender, ExceptionFilterEventArgs e)
    {
        if(ErrorFiltering.Filter(new HttpContextWrapper(e.Context)))
        {
            e.Dismiss();
        }
    }

    and in another file somewhere (note the HttpContextWrapper in both of these pieces of code, for easier testing):

    public class ErrorFiltering
    {
        public static bool Filter(HttpContextWrapper httpContextWrapper)
        {
            return httpContextWrapper.Request.IsLocal;
        }
    }
  7. Run the SQL script included with the ELMAH download to generate the needed table and stored procedures, then hookup SQL security and the connection string from the previous steps

You should be good to go now, ripe with error logging goodness. For added user friendliness, we use the following in our web.config to redirect users to nice pages when an error pops up:

<customErrors mode="RemoteOnly" defaultRedirect="~/Errors/Generic.html">
    <error statusCode="404" redirect="~/Errors/NotFound.html" />
    <error statusCode="500" redirect="~/Errors/Internal.html" />
</customErrors>

The only thing that buggs me about using ELMAH is how Resharper acts with it. The SectionHandler’s defined in the sectionGroup in the web.config (from step 2 above) are internal to the ELMAH assembly, so Resharper freaks out that saying they’re not defined. Bzzt. Sorry, Resharper, try again. So I’ve simply built a local version of the project with those attributes marked as public and it’s all good. I’m looking into filing a bug report with Resharper on this issue now, as it does it with log4net too. Quite annoying when you have the Solution-wide Analysis option turned on and the web.config consistently shows up with “errors”.

7 Responses

  1. Steve Says:

    Thank you for this information! Very helpful.

    (You do have a typo above on ’email’ section where the opening and closing tags don’t match)

  2. Error Logging Modules and Handlers for ASP.NET at { null != Steve } Says:

    […] followed Darrell Mozingo’s blog post here http://darrell.mozingo.net/2009/02/19/elmah-with-aspnet-mvc/ for setting it up with asp.net […]

  3. Marnix Says:

    Thanks Darrell, nice summary.

    The sample error filter however is broken. e.Context is of type HttpContext, casting it to HttpContextWrapper results in null.

    Also, there is a handy IsLocal property on Request. If you use that, you don’t have to parse the URL.

  4. Darrell Mozingo Says:

    @Steve: Thanks, fixed that email section typo.

    @Marnix: Quite right, good catch. I must have manually changed it before posting for some reason. The HttpContextWrapper constructor can take in an HttpContext, which is how I should have done it. Fixed that and updated to use the IsLocal property – quite handy. Thanks.

  5. alfredo Says:

    I am unable to access the error log in windows server 2008

  6. Darrell Mozingo Says:

    @alfredo: Can you elaborate a little more?

  7. Andrew lewis Says:

    Nice article! Simple and concise.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.