Configuring ELMAH with WCF using NuGet

I am sure most of you have used Error Logging Module and Handlers (ELMAH) for ASP.NET. ELMAH is one great open source project and real blessings for ASP.NET developers. If you don’t know about it, It’s a MUST SEE tool and in that case I would recommend you to read out Scott Ha introductory blog post on ELMAH.

BUT, in this post we are going to see how to configure ELMAH to work with WCF services because if you do that in a typical way then ELMAH is probably not going to work as expected and it won’t show you any unhandled exception.

So let’s get started!

ElmahWithWcfSolution

I have created a new WCF Application project ElmahWithWcf containing one contract IDemoService and service implementation class DemoService.

To add ELMAH, you can either download it from project host site and configure it or you can simply use NuGet to download and automatically install/configure ELMAH.

NuGet is a Visual Studio extension that makes it easy to install and update open source libraries and tools in Visual Studio. Perhaps it really does simplify the life of developer when it comes to configure third party open source libraries. If you haven’t used NuGet, I would strongly encourage you to install it from Visual Studio Extension Manager (Tools –> Extension Manager). It’s free. You can also read NuGet documentation on CodePlex.com for further help or ping me back.

Once you have installed it, you can Add/Configure ELMAH via “Add Library Package Reference” in context menu of references folder.

In Add Library Package Reference, search elmah in online packages and click install, which will automatically download the required assemblies and configure entries in web.config as well. Isn’t it cool?

Add Library Package Reference

Just in case if you don’t believe, with NuGet you get all the config entries automatically!!!

Config Entries by NuGet

With this ELMAH is now configured as you would typically do in ASP.NET web application, however, in contrast to ASP.NET app, it won’t log any unhandled exception that is raised in WCF service. For this, to work correctly, you need to create custom Error Handler implementing IErrorHandler as demonstrated in code snippet below:

public class ElmahErrorHandler: IErrorHandler 
{
    #region IErrorHandler Members
    
    public bool HandleError(Exception error) 
    {
        return false;
    }
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    {
        if (error == null) 
        {
            return;
        }
   
        if (HttpContext.Current == null) 
        {
            return;
        }
   
        Elmah.ErrorSignal.FromCurrentContext().Raise(error);
    }
  
    #endregion
 }
 
 //Further in addition to that, you need to create a Service Behavior Attribute implementing Attribute and IServiceBehavior 

  public class ServiceErrorBehaviorAttribute: Attribute, IServiceBehavior 
  {
    private readonly Type errorHandlerType;
    public ServiceErrorBehaviorAttribute(Type errorHandlerType) 
    {
        this.errorHandlerType = errorHandlerType;
    }
    
    #region IServiceBehavior Members 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection < ServiceEndpoint > endpoints, BindingParameterCollection bindingParameters) 
    {
    }
    
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    {
        IErrorHandler errorHandler;
        errorHandler = Activator.CreateInstance(errorHandlerType) as IErrorHandler;
        if (errorHandler != null) 
        {
            foreach(ChannelDispatcherBase dispatcher in serviceHostBase.ChannelDispatchers) 
            {
                ChannelDispatcher cd = dispatcher as ChannelDispatcher;
                cd.ErrorHandlers.Add(errorHandler);
            }
        }
    } 
  
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    {    
    }
    
    #endregion
 } 
 
 //And finally you need to apply the custom attribute on your service implementation class   
 [ServiceErrorBehavior(typeof(ElmahErrorHandler))]
 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
 public class DemoService: IDemoService 
 {
     #region IDemoService Members 
     public string GetData(int value) 
     {
        throw new Exception("TEST");
        return string.Format("You entered: {0}", value);
    }
    
    #endregion
 }

That is all you need to do for ELMAH to work with WCF.

 

At this point, ELMAH must show all unhandled exception in log file. For example, line number 9 throws an exception with message “Test”. If we invoke the service method, the ELMAH should log this exception. The log file can be browsed at http://ServerPath/elmah.axd

In fact, ELMAH is so convenient that we decided not to use Enterprise Library Logging Block and utilized ELMAH to log even handled exception as well (Yes another reason was timelines as well).

Did I hear How? Well, in that case you simply need to manually add one line in catch block.

image

This will inform/raise about the exception to ELMAH and so it will log the handled exception as well.

Hope this Helps!

In case of any feedback/experience, please do share…

Happy Coding!

ValidateRequest=”false” in ASP.NET 4

If you are someone like me who have recently upgrade to ASP.NET 4.0, you may have come across Yellow Screen of Death with Http Request Validation Exception, something like:

“A potentially dangerous Request.Form value was detected from the client”


Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client
Surprisingly, you will still see this exception even if you have set ValidateRequest to false in either the Page Tag or Web.Config.
ValidateRequest="false" or  <pages validateRequest="false" />
This may end you being freak out identifying the problem.
The solution is perhaps very simple. I would recommend to go and read ASP.NET 4 Breaking Changes.
“In ASP.NET 4, by default, request validation is enabled for all requests, because it is enabled before the BeginRequest phase of an HTTP request. As a result, request validation applies to requests for all ASP.NET resources, not just .aspx page requests. This includes requests such as Web service calls and custom HTTP handlers. Request validation is also active when custom HTTP modules are reading the contents of an HTTP request.and therefore request validation errors might now occur for requests that previously did not trigger errors.”
In order to revert to the behavior we had previously, you need to add the following setting in Web.config file:
<httpRuntime requestValidationMode="2.0"/>
And this should work!
Hope this helps!