Click here to Skip to main content
13,704,075 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

(untagged)

Stats

19.7K views
10 bookmarked
Posted 22 Apr 2015
Licenced CPOL

WCF Global Exception Handling

, 22 Apr 2015
Rate this:
Please Sign up or sign in to vote.
WCF Global Exception Handling

In WCF, all unhandled exceptions can be handled globally to avoid the service client going in to fault state.

  1. Implement IErrorHandler as follows:
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;
    
    namespace WcfService1
    {
        public class GlobalErrorHandler : IErrorHandler
        {
            /// <summary>
            /// The method that's get invoked if any unhandled exception raised in service
            /// Here you can do what ever logic you would like to. 
            /// For example logging the exception details
            /// Here the return value indicates that the exception was handled or not
            /// Return true to stop exception propagation and system considers 
            /// that the exception was handled properly
            /// else return false to abort the session
            /// </summary>
            /// <param name="error"></param>
            /// <returns></returns>
            public bool HandleError(Exception error)
            {
                return true;
            }
    
            /// <summary>
            /// If you want to communicate the exception details to the service client 
            /// as proper fault message
            /// here is the place to do it
            /// If we want to suppress the communication about the exception, 
            /// set fault to null
            /// </summary>
            /// <param name="error"></param>
            /// <param name="version"></param>
            /// <param name="fault"></param>
            public void ProvideFault(Exception error,
                System.ServiceModel.Channels.MessageVersion version,
                ref System.ServiceModel.Channels.Message fault)
            {
                var newEx = new FaultException(
                    string.Format("Exception caught at Service Application 
    			GlobalErrorHandler{0}Method: {1}{2}Message:{3}",
                    Environment.NewLine, error.TargetSite.Name, 
                    Environment.NewLine, error.Message));
    
                MessageFault msgFault = newEx.CreateMessageFault();
                fault = Message.CreateMessage(version, msgFault, newEx.Action);
            }
        }
    }
  2. Then implement IServiceBehavior and extend Attribute class as follows:
    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace WcfService1
    {
        public class GlobalErrorBehaviorAttribute : Attribute, IServiceBehavior
        {
            private readonly Type errorHandlerType;
    
            /// <summary>
            /// Dependency injection to dynamically inject error handler 
            /// if we have multiple global error handlers
            /// </summary>
            /// <param name="errorHandlerType"></param>
            public GlobalErrorBehaviorAttribute(Type errorHandlerType)
            {
                this.errorHandlerType = errorHandlerType;
            }
    
            #region IServiceBehavior Members
    
            void IServiceBehavior.Validate(ServiceDescription description, 
                ServiceHostBase serviceHostBase)
            {
            }
    
            void IServiceBehavior.AddBindingParameters(ServiceDescription description, 
                ServiceHostBase serviceHostBase,
                Collection<ServiceEndpoint> endpoints, 
                BindingParameterCollection parameters)
            {
            }
    
            /// <summary>
            /// Registering the instance of global error handler in 
            /// dispatch behavior of the service
            /// </summary>
            /// <param name="description"></param>
            /// <param name="serviceHostBase"></param>
            void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, 
                ServiceHostBase serviceHostBase)
            {
                IErrorHandler errorHandler;
    
                try
                {
                    errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
                }
                catch (MissingMethodException e)
                {
                    throw new ArgumentException("The errorHandlerType specified 
                    in the ErrorBehaviorAttribute constructor must have a 
                    public empty constructor.", e);
                }
                catch (InvalidCastException e)
                {
                    throw new ArgumentException("The errorHandlerType specified 
                    in the ErrorBehaviorAttribute constructor 
                    must implement System.ServiceModel.Dispatcher.IErrorHandler.", e);
                }
    
                foreach (ChannelDispatcherBase channelDispatcherBase in 
                serviceHostBase.ChannelDispatchers)
                {
                    ChannelDispatcher channelDispatcher = 
                            channelDispatcherBase as ChannelDispatcher;
                    channelDispatcher.ErrorHandlers.Add(errorHandler);
                }
            }
    
            #endregion IServiceBehavior Members
        }
    }

Now you are almost done. You just need to decorate your service class as follows:

using System;

namespace WcfService1
{
    [GlobalErrorBehaviorAttribute(typeof(GlobalErrorHandler))]
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            throw new NotImplementedException();
            //return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Please note:

It is good practice to handle the exceptions at the methods that raises the exception. But sometimes, we may need a global solution for handling un-handled exceptions to avoid client objects going into fault state.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Acharya Raja Sekhar
Software Developer (Senior)
India India
Working as a Senior Developer in an MNC with 3+ years of experience in .Net related technologies. Passionate about programming and software architecture.

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180920.1 | Last Updated 22 Apr 2015
Article Copyright 2015 by Acharya Raja Sekhar
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid