wcfierrorhandlerservicebehavior

ServiceBehavior for WCF REST


I have a problem configuring a ServiceBehavior for my WCF service.

Some background. Basically I am developing a REST service WCF that is supposed to run on IIS. I need to be able to log exceptions thrown by the service (I'm using log4net) and return HTTP status codes depending on the type of exception. I want my service implementation to have a minimum knowledge of WCF related stuff, so I don't want to convert the exceptions to FaultException everywhere in the service. So I figured out that adding my own IErrorHandler to the service host would be the best way to do it.

My problem is however that no matter what I try I can't seem to get the configuration for my custom ServiceBehavior right in Web.config. Here is the relevant code.

Web config.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </modules>
</system.webServer>

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior name="UsingErrorLogBehavior">
        <errorLogBehavior/>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior>
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <extensions>
    <behaviorExtensions>
      <add name="errorLogBehavior"
           type="MyNameSpace.Web.ErrorExtensionElement, MyNameSpace.Web"/>
    </behaviorExtensions>
  </extensions>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  <standardEndpoints>
    <webHttpEndpoint>
      <standardEndpoint name="" helpEnabled="true" 
                        automaticFormatSelectionEnabled="false" 
                        defaultOutgoingResponseFormat="Json" 
                        maxReceivedMessageSize="4194304" transferMode="Buffered" />
    </webHttpEndpoint>
  </standardEndpoints>
</system.serviceModel>

ErrorExtensionElement.

namespace MyNameSpace.Web
{
    public class ErrorExtensionElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(ErrorServiceBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new ErrorServiceBehavior();
        }
    }
}

ErrorServiceBehavior.

namespace MyNameSpace.Web
{
    public class ErrorServiceBehavior : IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                channelDispatcher.ErrorHandlers.Add(new ExceptionModule());
            }
        }

        public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }
    }
}

Where ExceptionModule implements IErrorHandler.


Solution

  • You have a <serviceBehavior> section named "UsingErrorLogBehavior", but no service configurations are referencing that section. You can either make that section the default service behavior (by not giving it a name, like you have for the endpoint behavior), or add a <service> element for your service which references that behavior:

    <services>
      <service name="YourNamespace.YourServiceName"
               behaviorConfiguration="UsingErrorLogBehavior">
        <endpoint address=""
                  binding="webHttpBinding"
                  contract="YourNamespace.YourContractName" />
      </service>
    </services>