The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication

前端 未结 14 1646
我寻月下人不归
我寻月下人不归 2020-12-04 05:43

The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

14条回答
  •  無奈伤痛
    2020-12-04 06:37

    To prevent the Server from fall in Fault state, you have to ensure that no unhandled exception is raised. If WCF sees an unexpected Exception, no more calls are accepted - safety first.
    Two possibilties to avoid this behaviour:

    1. Use a FaultException (this one is not unexpected for WCF, so the WCF knows that the server has still a valid state)
      instead of

      throw new Exception("Error xy in my function")  
      

      use always

      throw new FaultException("Error xy in my function")  
      

      perhaps you can try..catch the whole block and throw a FaultException in all cases of an Exception

      try   
      {  
          ... some code here   
      }
      catch (Exception ex)
      {  
          throw new FaultException(ex.Message)   
      }
      
    2. Tell WCF to handle all Exceptions using an Errorhandler. This can be done in several ways, I chose a simple one using an Attribute:
      All we have to do more, is to use the attribute [SvcErrorHandlerBehaviour] on the wanted Service Implementation

      using System;
      using System.Collections.ObjectModel;
      using System.ServiceModel;
      using System.ServiceModel.Channels;
      using System.ServiceModel.Description;
      using System.ServiceModel.Dispatcher;
      
      namespace MainService.Services
      {
          /// 
          /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
          /// 
          public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
          {
              public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
              { } //implementation not needed
      
              public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints,
                                               BindingParameterCollection bindingParameters)
              { } //implementation not needed
      
              public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
              {
                  foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
                  {
                      ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
                      if (channelDispatcher == null)
                          continue;
                      channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
                  }
              }
          }
      
          public class SvcErrorHandler: IErrorHandler
          {
              public bool HandleError(Exception error)
              {
                  //You can log th message if you want.
                  return true;
              }
      
              public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
              {
                  if (error is FaultException)
                      return;
      
                  FaultException faultException = new FaultException(error.Message);
                  MessageFault messageFault = faultException.CreateMessageFault();
                  msg = Message.CreateMessage(version, messageFault, faultException.Action);
              }
          }
      }
      

    This is an easy example, you can dive deeper into IErrorhandler by not using the naked FaultException, but a FaultException<> with a type that provides additional info see IErrorHandler for an detailed example.

提交回复
热议问题