12

无法使用正确的 web.config 将 IErrorHandler 集成到我的项目中

我有一个成功工作的 WCF,它被 .net 4 中的 webclients 使用,但是当尝试将 IErrorhandler 设置为全局错误记录器作为我所有服务方法的全部捕获时,事情很快就失败了 - 主要与 web.config 部分有关!请帮忙。

这三个服务分别是:IReport、IServiceCustomer、IServiceUser

在名为 MyErrorClass.cs 的单独类中实现 IErrorHandler,如下所示:

namespace CustomerWcfService
{
public class WcfErrorHandler : IErrorHandler
{
   /// <summary>
    /// Enables the creation of a custom <see cref="T:System.ServiceModel.FaultException`1"/> that is returned from an exception in the course of a service method.
    /// </summary>
    /// <param name="error">The <see cref="T:System.Exception"/> object thrown in the course of the service operation.</param><param name="version">The SOAP version of the message.</param><param name="fault">The <see cref="T:System.ServiceModel.Channels.Message"/> object that is returned to the client, or service, in the duplex case.</param>
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        // can create custom error messages here
    }

    /// <summary>
    /// Enables error-related processing and returns a value that indicates whether the dispatcher aborts the session and the instance context in certain cases. 
    /// </summary>
    /// <returns>
    /// true if  should not abort the session (if there is one) and instance context if the instance context is not <see cref="F:System.ServiceModel.InstanceContextMode.Single"/>; otherwise, false. The default is false.
    /// </returns>
    /// <param name="error">The exception thrown during processing.</param>
    public bool HandleError(Exception error)
    {
        // log error to database using legacy error handler
        ErrorHandler.LogError(error);

        // Let the other ErrorHandler do their jobs
        return true;
    }
}

public class WcfErrorServiceBehaviour : IServiceBehavior
{
    /// <summary>
    /// Provides the ability to inspect the service host and the service description to confirm that the service can run successfully.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param><param name="serviceHostBase">The service host that is currently being constructed.</param>
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {   }

    /// <summary>
    /// Provides the ability to pass custom data to binding elements to support the contract implementation.
    /// </summary>
    /// <param name="serviceDescription">The service description of the service.</param><param name="serviceHostBase">The host of the service.</param><param name="endpoints">The service endpoints.</param><param name="bindingParameters">Custom objects to which binding elements have access.</param>
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {   }

    /// <summary>
    /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param><param name="serviceHostBase">The host that is currently being built.</param>
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        var handler = new WcfErrorHandler();
        foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            dispatcher.ErrorHandlers.Add(handler);
        }
    }
}

public class WcfErrorHandlerBehaviour : BehaviorExtensionElement
{
    /// <summary>
    /// Creates a behavior extension based on the current configuration settings.
    /// </summary>
    /// <returns>
    /// The behavior extension.
    /// </returns>
    protected override object CreateBehavior()  {   return new WcfErrorServiceBehaviour();  }

    /// <summary>
    /// Gets the type of behavior.
    /// </summary>
    /// <returns>
    /// A <see cref="T:System.Type"/>.
    /// </returns>
    public override Type BehaviorType   {   get { return typeof (WcfErrorServiceBehaviour); }   }
}
}

web.config 应该是什么样子,因为我已经从网上的各种教程和答案中尝试了一百万种组合,但没有让它工作!当我不涉及 IErrorHandler 时,这就是 web.config 的原始工作摘录的样子

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>

请有人可以将更正后的 web.config 发送给这个 WCF 菜鸟,因为我一直在删除并重试,却无处可去(我为此浪费了很多天):(

4

2 回答 2

15
<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
        <serviceMetadata httpGetEnabled="true" />
        <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
        <serviceDebug includeExceptionDetailInFaults="true" />
        <errorHandler/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  <extensions>
    <behaviorExtensions>
      <add name="errorHandler" type="CustomerWcfService.WcfErrorHandlerBehaviour, CustomerWcfService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </behaviorExtensions>
  </extensions>
</system.serviceModel>

然后将您的行为应用于您希望将其应用于的服务。

编辑 :

抱歉错过了,但您实际上需要删除扩展定义中类型名称中的任何换行符和任何额外的空格(旧的 WCF 错误,它强制您在扩展类型声明中使用完全限定的名称字符串)。

于 2012-09-14T14:43:02.583 回答
8

有点晚了,但对于其他用户来说,这里是一个更好的方法(在我看来),上面的代码只需要稍微改变一下

你可以改变:

    public class WcfErrorServiceBehaviour : IServiceBehavior

至:

    public class WcfErrorServiceBehaviourAttribute : Attribute, IServiceBehavior

现在您可以将其用作服务类的属性,如下所示:

    [WcfErrorServiceBehaviour]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
                     ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class MXServiceCommands : IMXServiceCommands
    {
    }

希望这对其他人有所帮助。

于 2015-05-22T08:16:43.970 回答