ASP.Net trapping errors using web.config


I'm trying to trap errors in my web app.
I started here
The article suggests  at least three ways of trapping and handling errors

I want to write userID, page that caused error and Error message to the database and maybe generate an email to myself of the error( let's not worry about the last bit yet). I am using Visual Studios 2008 .

Keeping in mind the latest ASP.Net security issue I think I want to use option 3.
My question is when would I write error details to the database?
Is it in Application_Error? will Application_Error fire even though I'm using <customErrors> in web.config
Or do I write to the dB in the code-behind of the default error page?

What are best practices for this?

Who is Participating?
naspinskiConnect With a Mentor Commented:
I just use ELMAH, it is simple to set up, free and open-source and all of this will be taken care of for you.
iftechAuthor Commented:
Thanks for the response.

I tried implementing ELMAH with very little success.

First: I get 404 error when I try: http://localhost:58730/elmah.axd

Second:  I have a www folder which is the root folder of the app In web.config I have
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/error.aspx" />
 so when I try: http://localhost:58730/www/elmah.axd
I get redirected to my default error page.  

Third: Nothing is being logged into the SQL server table Elmah_error.

Here are the parts of web.config:

See nay issues? thanks.

    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
			<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
				<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
				<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
					<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
					<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
					<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
					<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
    <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" />
    <security allowRemoteAccess="yes" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="Data Source=testbox\testbox08;Initial Catalog=eDENT;User ID=xxx;Password=xxxx" />

            Set compilation debug="true" to insert debugging 
            symbols into the compiled page. Because this 
            affects performance, set this value to true only 
            during development.
    <!--ASP.Net Security work around & ELMAH-->
    <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/error.aspx" />
    <!--ASP.Net Security work around-->

      <add  verb="*" path="*.jpg" type="Thumb.ThumbnailHandler" />
      <add  verb="*" path="*.jpeg" type="Thumb.ThumbnailHandler" />
      <add  verb="*" path="*.gif" type="Thumb.ThumbnailHandler" />
			<remove verb="*" path="*.asmx" />
			<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
			<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
			<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />
      <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />

			<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />

Open in new window

So what I would do is set customErrors mode to RemoteOnly in the web.config (this will prevent the security vulnerability). Then in the Application_Error method in the global.asax do your error handling where you'll write to the database and possibly send an email.

Things that are useful to know in Application_Error:
1. You can access the exception that was thrown with System.Web.HttpContext.Current.Server.GetLastError()
2. You can access session variables with System.Web.HttpContext.Current.Session["VarName"]
3. You can access posted data with System.Web.HttpContext.Current.Request.Form["FieldName"]
4. As long as you don't do a response.redirect or response.end in Application_Error you will not be vulnerable to the vulnerability
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Do you have the elmah dll in your bin or registered on your server?
Craig WagnerSoftware ArchitectCommented:
Setting customErrors to RemoteOnly is not the only thing you need to do to prevent the vulnerability. Unfortuantely crisco96's response leaves out a few rather important steps from what you need to do. As Phil Haack said in a recent blog post, "I’ve seen a lot of questions about [ScottGu’s] mitigations, as well as a lot of bad advice. The best advice I’ve seen is this - if you’re running an ASP.NET application, follow the advice in Scott’s blog to the letter. Better to assume your site is vulnerable than to second-guess the mitigation."

Here is a link to ScottGu's suggestions. Be sure to follow the link in this post to his first post you follow ALL the steps needed.

Back to your question...

Application_Error will fire if you have the using customErrors mode set to Off or RemoteOnly.

As long as you are using redirectMode="ResponseRewrite" on your customErrors tag, you will be able to access the exception that caused the problem from your error page using Server.GetLastError(). I believe you lose the Session variables though.

There isn't one and only one way to skin this cat. If you have information you need to get from Session or the Request you should get that information in Application_Error (it's the only place that information is available).

In one web site I've developed we have code in Application_Error that gathers everything we want to log from GetLastError and Session, writes to the log, and then allows the .NET framework (via customErrors) to redirect to the error page.

Another application I wrote I didn't need anything from Session, so rather than splitting the responsibilities between two different classes I decided to do all the logging in the error page.

One advantage of doing everything in the error page is that there are certain types of errors that won't trigger Application_Error because .NET doesn't ever forward the request to your code, it just immediately triggers an error condition. Requesting the WebResource.axd (as the vulnerability does) bypasses the Application_Error event altogether.
It looks to me like Craig simply reiterrated what Crisco said, but first said it's a bad thing and then said that's what he does himself. He also simply gave information on the recently announced security vulnerability which the OP obviously knows about.

The biggest keys are:
1) do not return different errors based on the error type (404 vs. 500)
2) application_Error will fire assuming the request hits your web app. Otherwise the IIS error handler will fire and show the ugly yellow and red error message, this is where the customerrors tag comes in.
3) Application_error will have acces to all server, error, form, and session variables through the HttpContext
4) Application_error can be used to send emails and store to a DB. Just make sure you don't have any errors in this code itself. Use try, catch, finally where appropriate.
iftechAuthor Commented:
I'm a little confused now. Should I  use Application_Error to log errors  or work on getting ELMAH to work correctly to log errors?  Any one better than the other?

Thanks for the responses guys. Really appreciate it.
Craig WagnerSoftware ArchitectCommented:

It appears you read about half of what I wrote before repeating most of ScottGu's advice and rewording what I stated. Your points, in order:

1. This can be obtained through the link to ScottGu's blog.
2. I stated this in my last paragraph.
3. This was stated by both crisco96 and myself.
4. This is equivalent to saying, "Anywhere you write code in your app can be used to send email..." Not exactly earth-shattering information in this point.

I did not simply reiterate what crisco96 said. I elaborated on it, stating that crisco96's advice was incomplete (he stated that all you have to do to avoid the vulnerability was add mode="RemoteOnly" to customErrors, which is not true). Rather than going into detail about what you are supposed to do, I simply pointed the OP to ScottGu's blog.

I also never said it was a bad thing. I answered one of the OP's direct questions ("will Application_Error fire even though I'm using <customErrors> in web.config") which no one had done until this point. I then pointed out the differences between using the two locations (Application_Error vs. error page). I provided information to help the OP make an informed decision about what was right for his environment, because there is no "right" or "wrong" answer to this question.

I respectfully request if you're going to criticize my comments, please take the time to fully read and comprehend them first.
Craig WagnerSoftware ArchitectCommented:

Define "better"?

ELMAH appears to give you more out-of-the-box functionality. It is code you don't have to maintain. If you have multiple applications it's a nice way to ensure they're all handled consistently.

On the other hand, if you write the handling code yourself you can control every aspect of what it does and make it do exactly what you want it to do. If you've only got one application and will never have any more perhaps the consistency isn't a big deal.

Unfortunately those are not questions we can answer for you. You have to look at your needs, your environment, your timeline and figure out for yourself what the best course of action is. There is almost never one right answer or silver bullet ( to a problem.
iftechAuthor Commented:

I do have both Elmah.dll and Elmah.pdb in the bin folder. Did you notice anything with web.config that isn't right?
I think I got got all the steps.

1) Place Elmah.dll in bin folder.
2) run SQLServer.sql on the db I want to create ELMAH_Error table and stored procedures (the table and the three procedures are there)
3) edit web.config as I showed above

I decided to go with ELMAH because I several projects I need to do this for. However I do not want to do it at the server level.

It all looks good to me.

Is this the newest version?  Maybe something has changed - have you checked with the documentation on the ELMAH site?
iftechAuthor Commented:
I downloaded it this week Monday to be exact, so I'm sure it's the newest version.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.