ASP.NET Error Handling - asp.net

In my asp.net applications, I've typically used the Application_Error global event handler to log the error and redirect the user to a user-friendly error page.
However, I have read about ELMAH and while that seems interesting, Application_Error seems like the simpler approach.
I've read other questions where people, including myself, have suggested one way or the other. What I'm wondering is if there is any significant benefit to using one over the other and why?

Elmah is a fantastic project and we use it for all of our ASP.NET applications. Not only does it log unhandled errors for you, it grabs the entire original page that the user saw, which contains a lot of detail for you.
It has email support, RSS feeds (both itemized and digest) and has an attractive console.
For 3 lines in config and a dll reference, I'd say that's a slam dunk.

I guess the main drawback of ELMAH is that it might be overkill for what you need. If it's logging and storing more info than you would in your own implementation, that's an unnecessary overhead in storage and processing. You also need to think about how you secure access to ELMAH's console since those exception details could contain juicy details of your app (that needn't be hard, but it's a worry that you didn't have before).
On the other hand, your own implementation will probably grow to log all that extra information once you decide that some stubborn bug requires it, and do you really care about shaving fractions of a second off the time that it takes for the error page to be displayed? Chances are you'll eventually end up building your own version of ELMAH, so why not just use ELMAH and save yourself the time.
I'd recommend that if you do want to write your own error logging rather than using ELMAH, you at least put it in a module rather than straight into Application_Error in global.asax. Just subscribe to the application's Error event in your module's Init method, and you can easily reuse your error handling code in another application with a line in web.config.
I also find it useful to handle any exception logging through ASP.NET's health monitoring. This makes it easy to control the type and level of logging in web.config, and also allows logging of exceptions that were handled in a try...catch without getting as far as Application_Error. Create a custom HandledExceptionEvent class that extends WebRequestErrorEvent, and you can create and raise those events in any catch block where you'd really like to know that the exception happened even though it was handled.

Related

Should I catch all my exceptions in the global.asax?

If I am just logging exception details in my web app, do I really need to put in exception handling logic for each tier? Why not just let them all bubble up the stack trace to the global.asax and log them there?
I would suggest against using any exception handling logic in any layer of your application unless:
The exception is not a fatal one, meaning that there is some action you can take to recover, or
The application should continue functioning and the exception should be "ignored." An example: when checking out at an online retailer you are sent a receipt via email. If that fails - but the other order processing stuff succeeds - the user should not be shown an error page. Here, we want the workflow to continue even though there is an exception. Most exceptions do not fall into this category.
Of course, exceptions - whether they are fatal or not or should be "ignored" or not - need to be logged and developers notified. This is best handled through an event handler for the Application.Error event. Yes, this can be done in Global.asax, but I think it's cleaner to use an HTTP Module-based approach, either Health Monitoring or ELMAH.
I've written an article on this topic that I'd like to recommend to you - Exception Handling Advice for ASP.NET Web Applications. Here is the article in summary:
My advice for handling exceptions in an ASP.NET application can be boiled down to the following guidelines:
(a) Create and use a meaningful custom error page.
(b) In general, do not catch exceptions. Let them bubble up to the ASP.NET runtime. Some cases where catching an exception makes sense include:
When there is a plausible way to recover from the exception by performing some alternative logic,
When a peripheral part of the application's workflow throws and exception and that exception should not derail the entire application, and
When you need to include additional information with the exception by throwing a new exception that has the original exception as its inner exception.
(c) Log all exceptions to some persistent store and use email (or some other medium) to notify developers when an exception occurs in production. Consider using ELMAH or ASP.NET's built-in Health Monitoring system to facilitate this process.
Exceptions should bubble up to whatever layer can handle them in a meaningful way, being aware of the Single Responsibility principle. For instance, your data layer should not be invested in logging.
The Application.Error event is a good place for catch-all error handling: that is, unexpected and/or fatal errors that require no special treatment beyond logging/alerting and redirecting to an error page.
If your web app makes use of the Microsoft AJAX extensions and partial postbacks, you'll need to handle exceptions in at least two places:
Global.asax
Your ScriptManager's OnAsyncPostBackError handler
For further information on OnAsyncPostBackError, check out:
http://msforge.net/blogs/janko/archive/2008/02/13/handling-exceptions-in-asp-net-ajax.aspx
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.onasyncpostbackerror.aspx
I say that on global try to catch the error that you miss on the logic steps of your program and redirect them on an "error page", or a "not found page".
All other errors not necessary show the error on the user, and not need to send it to an error page.
For example, in page with 2 or more, different modules, if the one throw an error, just hide it, and show the rest. Similar try to catch errors when they happens and handle them the best non visual way to the user if this is possible, log them and correct them later.
Now this error that happens only on one module, you can see it on your log and correct it, but until you do that, user see something on your page and not a full error page.
Usually what I do is do a try...catch in the code, but instead of logging on the catch what I do is pass it on with a message stating where the error came from, etc. Then I use Elmah to catch all of the errors and log them.
That way you only have to deal with the logging in one area and satisfy the Single Responsiblity Principle, but you have more information available for debugging purposes. It can also be helpful when you get that data error that only seems to occur with 1 out of 500 users.

Exception handling in a three-tier Asp.Net application

1) To my understanding, in a three-tier Asp.Net application we should implement exception handling in the following way:
a - we should put try-catch block around block of code ( located in any of the three layers ) from which we expect the page to gracefully recover from ( when this code generates an exception )?
b - we shouldn’t put try-catch blocks around code ( located in either of the three layers ) from which we don’t expect the page to gracefully recover from. Instead, Asp.Net application should always manage these unhandled exceptions through global exception handler ( Application_Error/Page_Error )?
2) Is the main benefit of managing unhandled exceptions through Application_Error/Page_Error the fact that this way we centralize error handling in one location?
After all, we could achieve the same results even if these unhandled exceptions (thrown in any of the three layers ) were instead handled ( logged, user redirected to custom error page ... ) at the spot where they were thrown?!
thank you
Not necessarily.
1a - it's quite acceptable for the data layer to have no exception handling. In which case any exception would be handled further up the stack.
1b - the data layer and business layer may not be called via a website, so a particular web page isn't necessarily relevant. For example, a webservice or WPF application may also use these layers.
2 - yes the main benefit is a single location for website error handling.
The main thing you want to avoid is silently swallowing exceptions that cannot be recovered from. (In short, having a try...catch block where you display some error to the user, but don't rethrow the exception, where thereby only the end user is aware that something went awry.)
If an exception happens and you can recover from it, great!
If an exception happens and you can't recover from it, then it is important that the exception details be logged and that the developers are notified of the exception. Typically this is done by letting the exception propagate to the ASP.NET runtime layer so that ASP.NET's Error event will fire. It's a best practice to subscribe to this Error event in some manner so as to log the error details and notify developers. One such tool for logging and notifying in the face of an error is ELMAH, another is the ASP.NET Health Monitoring library.
Also, if I may, I'd suggest this article of mine, which covers the points I made in here more depth and detail: Exception Handling Advice for ASP.NET Web Applications.
Happy Programming!
1a) is correct.
1b) is sort of correct; you may let the exception go up the stack from your model/business layers to the presentation, and display an error message. It doesn't have to go all the way to the Application_Error; Page_Error may be good, but some exceptions might be (relatively) common enough that, while you can not gracefully recover, you should have specific error messages related to them in some contexts.
2) basically; and also as a 'catch all' for exceptions you have not been able to predict and catch in more specific places.

detecting undisposed web service calls (ASP.NET)

I'm inheriting a legacy project, and there's a page that calls a method that makes a web service call. Load and performance testing has detected that this page sometimes takes a really long time to close, but usually it's fine, and if there is one hanging, all other requests for that page hang until the first one resolves, and then they all resolve.
I think this might have something to do with the web service being instantiated and not disposed, but I don't know how I can be more sure. I tried to add a delegate to the Dispose method but that doesn't seem to ever fire. (I'm not sure it would without Dispose being called explicitly, but that doesn't really matter.)
So what can I look for on the production server or any deployed environment to watch those requests pile up and go out (or get handled in an orderly manner, if they aren't the problem)?
You might consider using a tool like .NET Memory Profiler. You can use it to attach to your running application, and it can find and report all undisposed objects.
I think they have a free two week trial.
In your web app code, you could write to a log (event log, text file) right before you send a request, and again right after you get the response. Include some identifying information about the request. Add timestamps.
If you only want to use this while debugging, wrap it in #debug.
Or if you want to test in release mode, you could put a boolean in appSettings in web.config so you could turn the logging off and on.

Exception Handling in .net web apps

I admit it: I don't bother with too much exception handling. I know I should do more but I can never wrap my head around where to start and where to stop. I'm not being lazy. Far from it. It's that I'm overwrought with exception handling ambivalence. It just seems that there is a seemingly infinite number of places in even the smallest app where exception handling can be applied and it can begin to feel like overkill.
I've gotten by with careful testing, validating, and silent prayer but this is a bad programming accident waiting to happen.
So, what are your exception handling best practices? In particular, where are the most obvious/critical places where exception handling should be applied and where are places where it should be considered?
Sorry for the vague the question but I really want to close the book on this once and for all.
Microsoft's Patterns & Practices team did a good job incorporating best practices of exception management into Enterprise Library Exception Handling Application Block
Event if wouldn't use Enterprise Library, I highly recommend you to read their documentation. P&P team describes common scenarios and best practices for exceptions handling.
To get you started I recommend read following articles:
Exception Handling on MSDN
Exception Management in .NET on MSDN
Exception Handling Best Practices in .NET on CodeProject
ASP.NET specific articles:
User Friendly ASP.NET Exception Handling
Global Exception Handling with
ASP.NET
Exception handling in C# and ASP
.Net
The golden rule with exception handling is:
"Only catch what you know how to handle"
I've seen too many try-catch blocks where the catch does nothing but rethrow the exception. This adds no value. Just because you call a method that has the potential to throw an exception doesn't mean you have to deal with the possible exception in the calling code. It is often perfectly acceptable to let exceptions propagate up the call stack to some other code that does know what to do.
In some cases, it is valid to let exceptions propagate all the way up to the user interface layer then catch and display the message to the user. It might be that no code is best-placed to know how to handle the situation and the user must decide the course of action.
I recommend you start by adding a good error page that catches all exceptions and prints a slightly less unfriendly message to the user. Be sure to log all details available of the exception and revise that. Let the user know that you have done this, and give him a link back to a page that will (probably) work.
Now, use that log to detect where special exception handling should be put in place. Remember that there is no use in catching an exception unless you plan to do something with it. If you have the above page in place, there is no use in catching database exceptions individually on all db operations, unless you have some specific way to recover at that specific point.
Remember: The only thing worse than not catching exceptions, is catching them and not doing nothing. This will only hide the real problems.
Might be more about exception handling in general than ASP.NET speific but:
Try to catch exceptions as close to
the cause as possible so that you
can record (log) as much information
about the exception as possible.
Include some form of catch all, last
resort exception handler at the
entry points to your program. In
ASP.NET this could be the
Application level error handler.
If you don't know how to "correctly" handle an exception let it bubble up to the catch all handler where you can treat it as an "unexpected" exception.
Use the Try***** methods in .NET
for things like accessing a
Dictionary. This helps avoid major
performance problems (exception
handling is relatively slow) if you
throw multiple exceptions in say a
loop.
Don't use exception handling to
control normal logic of your
program, e.g. exiting from a loop via
a throw statement.
Start off with a global exception handler such as http://code.google.com/p/elmah/.
Then the question comes down to what kind of application are you writting and what kind of user experience do you need to provide. The more rich the user experience the better exception handling you'll want to provide.
As an example consider a photo hosting site which has disk quotas, filesize limits, image dimension limits, etc. For each error you could simply return "An error has occured. Please try again". Or you could get into detailed error handling:
"Your file is to large. Maximum
filesizes is 5mb."
"Your image is is
to large. Maximum dimensions are
1200x1200."
"Your album is full.
Maximum storage capacity is 1gb".
"There was an error with your
upload. Our hampsters are unhappy.
Please come back later."
etc. etc.
There is no one size fits all for exception handling.
Well at the very basic level you should be handling the HttpApplication.Error event in the Global.asax file. This should log any exception that occurs to a single place so you can review the stack trace of the exception.
Apart from this basic level you should ideally be handling exceptions where you know you can recover from them - for example if you expect a file might be locked then handling the IOException and reporting the error back to the user would be a good idea.

How do you log errors (Exceptions) in your ASP.NET apps?

I'm looking for the best way to log errors in an ASP.NET application.
I want to be able to receive emails when errors occurs in my application, with detailed information about the Exception and the current Request.
In my company we used to have our own ErrorMailer, catching everything in the Global.asax Application_Error. It was "Ok" but not very flexible nor configurable.
We switched recently to NLog. It's much more configurable, we can define different targets for the errors, filter them, buffer them (not tried yet). It's a very good improvement.
But I discovered lately that there's a whole Namespace in the .Net framework for this purpose : System.Web.Management and it can be configured in the healthMonitoring section of web.config.
Have you ever worked with .Net health monitoring? What is your solution for error logging?
I use elmah. It has some really nice features and here is a CodeProject article on it. I think the StackOverflow team uses elmah also!
I've been using Log4net, configured to email details of fatal errors. It's also set up to log everything to a log file, which is invaluable when trying to debug problems. The other benefit is that if that standard functionality doesn't do what you want it to, it's fairly easy to write a custom appender which can process the logging information as required.
Having said that, I'm using this in tandem with a custom error handler which sends out a html email with a bit more information than is included in the standard log4net emails - page, session variables, cookies, http server variables, etc.
These are both wired up in the Application_OnError event, where the exception is logged as a fatal exception in log4net (which then causes it to be emailed to a specified email address), and also handled using the custom error handler.
First heard about Elmah from the Coding Horror blog entry, Crash Responsibly, and although it looks promising I'm yet to implement it any projects.
I've been using the Enterprise Library's Logging objects. It allows you to have different types of logging (flat file, e-mail, and/or database). It's pretty customizable and has a pretty good interface for updating your web.config for the configuration of the logging. Usually I call my logging from the On Error in the Global.asax.
Here's a link to the MSDN
I use log4net and where ever I expect an exception I log it to the appropriate level. I tend not to re-throw the exception because it doesn't really allow for as-nice user experience, there is less info you can provide at the current state.
I'll have Application_Error also configured to catch any exception which was not expected and the error is logged as a Fatal priority through log4net (well, 404's are detected and logged as Info as they aren't that high severity).
My team uses log4net from Apache. It's pretty lightweight and easy to setup. Best of all, it's completely configurable from the web.config file, so once you've got the hooks in your code setup, you can completely change the way logging is done just by changing the web.config file.
log4net supports logging to a wide variety of locations - database, email, text file, Windows event log, etc. My team has it configured to send detailed error information to a database, and also send an email to the entire team with enough information for us to determine in which part of the code the error originated. Then we know who is responsible for that piece of code, and they can go to the database to get more detailed information.
I recently built an asp.net webservice with NLog, which I use for all my desktop apps. The logging works fine when I'm debugging in Visual Studio, but as soon as I switch to IIS the log file isn't created; I've not yet determined why, but it the fact that I need to look for a solution makes me want to try something else for my asp.net needs!
We use EnterpriseLibrary.ExceptionHandling.Logging. I like it a bit better than log4net because not only do we control the logging completely, but we can control the Throw/NoThrow decision within config as well.
We use a custom homegrown logging util we wrote. It requires you to implement logging on your own everywhere you need it. But, it also allows you to capture a lot more than just the exception.
For example our code would look like this:
Try
Dim p as New Person()
p.Name = "Joe"
p.Age = 30
Catch ex as Exception
Log.LogException(ex,"Err creating person and assigning name/age")
Throw ex
End Try
This way our logger will write all the info we need to a SQL database. We have email alerts set up at the DB level to look for certain errors or frequently occurring errors. It helps us identify exactly where the errors are coming from.
This might not be exactly what you're looking for. Another approach similar to using Global.asax is to us a code injection technique like AOP with PostSharp. This allows you to inject custom code at the beginning and end of every method or on every exception. It's an interesting approach but I believe it may have a heavy performance overhead.

Resources