If you've ever built a service or web site and deployed it to a remote system then you most likely know the headaches that come along with debugging them. Exceptions can occur on the remote system. Usually, ASP.NET sites will give you a yellow screen of death, but what about WCF services? Exceptions that occur on WCF services cause the service instance to terminate and the exception is swallowed. The user usually receives a TimeOut exception on the client side or some other arbitrary notice. How does one go about collecting and logging exceptions that happen in WCF services? You could wrap try/catch around every method body you create and add logging to the catch or, you can use ELMAH.
ELMAH (Error Logging Modules and Handlers) is a library that plugs-in to your ASP.NET site and logs unhandled exceptions. There is a great article about ELMAH already on DotNetSlackers http://dotnetslackers.com/articles/aspnet/errorloggingmodulesandhandlers.aspx . When it comes to ASP.NET sites, the beauty of ELMAH is that there is no work to get it going. You simply run a TSQL script to create the tables, add the DLL to your project directory and add two entries to the web.config and you're done! ELMAH logs exception details to a database with tons of useful information including the stack trace. You can even use the same ELMAH tables for multiple applications as it will keep track of which application it is logging data for which means you can have a central location for storing error data. ELMAH also provides a built in viewer which can be accessed via your project URL to see exception details in a friendly way.
Yes, ELMAH is a great tool to have for development and production ASP.NET sites. However, ELMAH was intended to work with ASP.NET sites and not other types of projects. This is because it takes advantage of the HttpContext to collect information for logging. So why, you ask, would I be talking about a library that was meant for ASP.NET sites being used on WCF services? Because you may be developing a WCF service that is hosted in IIS and you just might want some error logging! Unfortunately, getting ELMAH to work with WCF services isn't as easy as plug-and-play. There is some work required.
First step is getting ELMAH. Visit http://code.google.com/p/elmah/ to download the latest version (1.1 as of April 2010). Once you get the zip file, extract the contents to a folder somewhere and browse to it since we will need to access its contents.
The first step is to setup the database. If you have not already started one, do so now and then come back. Inside of the db folder, you'll see Oracle.sql and SQLServer.sql. For this article, I'm assuming you're using MS SQL so open the SQLServer.sql in Management Studio and run it against your database. You will receive a warning message; just ignore it as long as there are no errors. If all goes well, you should see a new ELMAH_Error table. The ELMAH script was originally meant to run on SQL 2000, but I've run it against 2005 and 2008 without any issues. If you see the new table, then you're done with this step.
If you don't already have a project yet, go ahead and create a new WCF Service Library in Visual Studio. Add a reference to System.Web. Once that's done add a reference to the ELMAH.dll found in the bin/net-3.5/Release folder where you extracted the ELMAH zip file contents.
Make sure everything builds and that ELMAH.dll actually goes into your bin folder when you build the project.
Getting it to work
As stated, this isn't just an easy plug-and-play scenario. There are some things that need to be done and code that must be written to get this off the ground.
We'll start by setting up the config. I refer to the web.config but you might have an app.config. The steps are the same. Browse to the <configSections> node (If you can't find it, you will have to add it under the
<configuration> node) in the web.config and add the following section group
Listing 1: Web.config :: Declaring ELMAH configuration section
What we're doing is telling our app that we want to add a new configuration section and we specify that the Elmah.ErrorLogSectionHandler knows how to read it. Next, the configuration section needs to be created. Find a good spot (I usually stick it right after the
<configSections> area) and add the following
Listing 2: web.config :: Defining ELMAH configuration section
What we've done here is defined our configuration options that ELMAH will use to determine what actions to take when an exception has occured. I've used a very simple setup for this article which only logs the data to the database. You will have to change the value of
connectionString attribute to reflect the name of a connection string that points to the database where the ELMAH table is located.
If you read the documentation, you'll see that you can set it up to send email alerts and many other actions in addition to database logging. I personally hate getting 20 emails a day, but that just because I'm lazy.
Now that we have ELMAH configured, we have to tell IIS what to do. ELMAH works as an HttpModule which gives it access to your app without you needing to add code. I assume that you're using IIS 7. If you're using IIS 6, then you will need to add the handlers and modules in the format required by IIS 6. If you can't find
<system.webServer> in your config, just add it in under the
<configuration> node. The following is a complete display of the
<system.webServer> node. If you already have an existing
<system.webServer> then just add the ELMAH handlers and modules to the appropriate sections.
Listing 3: Web.config :: system.webServer
Our last step enables ASP.NET compatibility to our service (this is how we get access to HttpContext). Under the
<system.serviceModel> node, add the following line
And we're done with the config.
This is where the similarities end between setting up ELMAH for ASP.NET and WCF services ends. We'd be done if this were an ASP.NET site. We have to have a behavior attribute and an error handler.
Create a new class file and name it 'ServiceErrorBehaviorAttribute.cs' and add the following class definition
Listing 4: ServiceErrorBehaviorAttribute.cs
You will need to add the following using references
This attribute, when applied to our service implementation, will add an error handler to every channel, specifying the type we passed in to the constructor which can be any type that implements IErrorHandler. Currently, we don't have one so let's make one.
Create another class file and name it 'ErrorHandler.cs' and add the following class definition
Listing 5: ErrorHandler.cs
Notice that in this code the comment, "In case we run outside of IIS". If no HttpContext object is available then it simply exits out. This has two implications; the first being that if the service is being run outside of IIS, no logging will occur. Secondly, if the service is running outside of IIS, ELMAH isn't going to bomb. No need to remove ELMAH for non IIS hosted services.
You will need to add the following using references
Now all that's left is to decorate our service with a few attributes and we're ready to go. Open the class file for your service implementation (not the service contract) and add the following attributes
And add the using reference
If you're a good developer and you organize your code properly, you will have to add some using references to resolve the classes you created for the ErrorHandler type and
At this point you can Build and test. Easiest way to test is purposely throw an error
If you use Management Studio and look in the ELMAH_Error table, you should see a row containing the exception information. As you're looking through the row data, you will notice that it's a bit of a pain to see the data this way. Let's look at the data in a different way. Open a browser window and browse to your service URL and append
This is the viewer that I mentioned above. From here you can see all of the errors that have been logged in a nice and easy to read layout. Now it's time to start fixing those bugs!
The only issues that I've encountered with getting ELMAH to work have been (other than IIS related issues) my connection strings. Be sure that the user account being used has EXECUTE permissions on the ELMAH stored procedures.
You also access the ELMAH viewer for hints on what is going wrong (you will see yellow screen of death).
Having the right tools can help you keep your sanity. WCF can be complicated enough without having to spend hours trying to track down bugs. Adding custom logging manually can be tedious and time consuming at best. Using ELMAH to log exceptions not only frees you from wasting time on writing custom logging code but also gives you some serious information to help resolve bugs. If you're sneaky, you can setup the email notifications and resolve bugs before anyone says anything about them which will make you look like a hero.
Dustin is a Microsoft C# MVP, Pluralsight author and producer of c0deporn.
This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.