简体   繁体   中英

WCF how to handle errors globally

So basically I want to handle exceptions in WCF services in centralized place. For that I created a class that implements IErrorHandler and a class that implements IServiceBehavior and in that Service Behavior implementation I am saying that for each channel dispatcher I want to add my custom error handler like this.

public void ApplyDispatcherBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
    IErrorHandler errorHandler = new CustomErrorHandler();
    foreach (var channelDispatcher in serviceHostBase.ChannelDispatchers)
    {
        channelDispatcher.ErrorHandlers.Add(errorHandler);
    }
}

and the final thing that I've done is created a class that derives from a BehaviorExtensionElement with appropriate implementation and registered the extension in config file. but it does not seem to work. I mean that thing I want to do is if exception stays unhandled I want to handle it somewhere in a centralized place. But it does not seem to work for me. Is my implementation correct, am I misunderstanding how this whole thing that I implemented should work. Any suggestion would be appreciated.

<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
    <bindings>
      <basicHttpBinding>
        <binding name="soapBinding" />
      </basicHttpBinding>
      <webHttpBinding>
        <binding name="webBinding" />
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="poxBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="defaultBehavior">
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="MyCustomBehaviorExtensionElement" type="MyNamespace.CustomExtensionElement, MyNamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <services>
      <service name="MyNamespace.MyService" behaviorConfiguration="defaultBehavior">
        <endpoint address="pox" binding="webHttpBinding" behaviorConfiguration="poxBehavior"
                  name="pox" contract="MyNamespace.IMyService" />
        <endpoint address="soap" binding="basicHttpBinding" bindingConfiguration="soapBinding"
                  name="soap" contract="MyNamespace.IMyService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/Services" />
          </baseAddresses>
        </host>
      </service>

here is the part of config file

Missed in your web config

In your case you haven't applied your extension, you need to add to your service behaviour your extension:

  <serviceBehaviors>
    <behavior name="defaultBehavior">
      <serviceDebug includeExceptionDetailInFaults="false" />
      <serviceMetadata httpGetEnabled="true" />

      <MyCustomBehaviorExtensionElement />
    </behavior>
  </serviceBehaviors>

WebHttpBinding:

But, for handling error for WebHttpBinding you have to use such approach:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using log4net;

namespace Server.Web
{
    public class WebHttpWithErrorHandlingElement : BehaviorExtensionElement
    {
        public class WebHttpWithErrorHandlingBehavior : WebHttpBehavior
        {
            internal sealed class WebHttpErrorHandler : IErrorHandler
            {
                private static readonly ILog logger = LogManager.GetLogger(typeof (WebHttpErrorHandler));

                public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
                {
                    var exception = new FaultException("Web Server error encountered. All details have been logged.");
                    var messageFault = exception.CreateMessageFault();

                    fault = Message.CreateMessage(version, messageFault, exception.Action);
                }

                public bool HandleError(Exception error)
                {
                    logger.Error(string.Format("An error has occurred in the Web service {0}", error));

                    return !(error is FaultException);
                }
            }

            protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                base.AddServerErrorHandlers(endpoint, endpointDispatcher);

                endpointDispatcher.DispatchRuntime.ChannelDispatcher.ErrorHandlers.Add(new WebHttpErrorHandler());
            }
        }

        public WebHttpWithErrorHandlingElement()
        {
        }

        public override Type BehaviorType
        {
            get { return typeof (WebHttpWithErrorHandlingBehavior); }
        }

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

Config file:

<system.serviceModel>
  <extensions>
    <behaviorExtensions>
      <add name="webHttpWhithErrorHanlding" type="Server.Web.WebHttpWithErrorHandlingElement, Server.Web"/>
    </behaviorExtensions>
  </extensions>


  <!-- other staff -->
  <behaviors>
    <endpointBehaviors>
      <behavior name="webBehavior">
        <webHttpWhithErrorHanlding />
      </behavior>
    </endpointBehaviors>

  </behaviors>
</system.serviceModel>

And then apply it to your endpoint:

  <service name="YourServiceContract">

    <endpoint address=""
              binding="webHttpBinding"
              behaviorConfiguration="webBehavior"
              contract="IYourServiceContract"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost/"/>
      </baseAddresses>
    </host>        
  </service>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM