locked
Communication Exception in WCF RRS feed

  • Question

  • Hi,

    I have WCF Services hosted as Windows Service and client is windows application. Client side I am geting an error "Object Reference is not set to instance of an object". But when I looked at client side Service Log I found

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

    This error is not consistent. I am getting this error on random basis. Sometimes when I restart the app this error goes away and sometimes app closes automatically after this error.

    Please someone help me how to resolve this error or how to throw a meaningful error at client side. Hot to stop a service going into Fault state.???

    Thanks in Advance... please this is urgent as app is gng into PROD in a week....

     

     

    Wednesday, August 25, 2010 1:58 AM

Answers

  • Hi htanias,

    On the service side, u need to create the errobehavior attribute class , which tells WCF that it should pass the errors to ur errorhandler. And the error handler will wrap all exception messages into FaultException("Message").And on the client side catch (FaultException) and it will not fault you channel anymore.

     Please find the below code for you problem (You can copy the complete "errorbehaviorattribute" and "errohandler classes they are in working condition).

    * Make sure you do not have includeExceptionDetailInFaults set to true as it will corrupt the channel.

     

     

     

    <serviceDebug includeExceptionDetailInFaults="true"/>  (default is false).

    --------------------------------------------------------------------------------------------------------

     

    My code below on service side will throw unhandled exception here: 

     //THIS LINE will throw AN ERROR.
     string h = yy.Title;

    SERVICE SIDE - CODE
    
     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
     [ErrorBehavior(typeof(MyErrorHandler))]
     public class Class1 : API.Interface1
     {
    
     public string HelloWorld()
     {
      return "HelloWorld";
     }
    
     
     public API.Class2 GetClass2()
     {
      Class2 xyz = new Class2();
      Class2 yy = default(Class2);
    
      //THIS LINE will throw AN ERROR.
      string h = yy.Title;
    
    
      return xyz;
     }
    
     
     }
    
     public class MyErrorHandler : IErrorHandler
     {
      public bool HandleError(Exception error)
      {
      return true;
      }
      public void ProvideFault(Exception error,MessageVersion version, ref Message fault)
      {
      FaultException faultException = new FaultException(error.Message);
      MessageFault messageFault = faultException.CreateMessageFault( );
      fault = Message.CreateMessage(version,messageFault,faultException.Action);
      }
     }
    
    
    
     public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
     {
    
     Type errorHandlerType;
    
    
     public ErrorBehaviorAttribute(Type errorHandlerType)
     {
    
      this.errorHandlerType = errorHandlerType;
    
     }
    
    
     public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
     {
    
     }
    
    
     public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase,Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
     {
    
     }
    
    
     public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
     {
    
      IErrorHandler errorHandler;
    
      errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
    
      foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
      {
    
      ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
    
      channelDispatcher.ErrorHandlers.Add(errorHandler);
    
      }
    
     }
    
     }
    
    

    Client Side code:

     

    class Program
     {
     static void Main(string[] args)
     {
    
      Class2 xyz = default(Class2);
      
      Interface1 proxy = new ChannelFactory<Interface1>(new WSHttpBinding()).CreateChannel(new EndpointAddress("http://localhost:11001/Class1"));
      try
      {
      xyz = proxy.GetClass2();
      }
      catch (FaultException ex)
      {
      
      }
      //Still able to call even after exception.
      Console.WriteLine(proxy.HelloWorld());
      Console.ReadLine();
     }
     }
    
    Thursday, August 26, 2010 5:32 PM

All replies

  • Hi I am not very sure, as I have started learning WCF recently.

    If there are unhandled errors being thrown from the service side, then it will be caught by the dispatcher and will get the channel to go into FaultedState. If you can wrap all the exceptions on the service side as a fault exception...Like any exception on the service side App Domain exception into a Fault Exception it should not cause your channel to go into faulted state.

     

    It also depends on what service instance mode you are using. 

    Wednesday, August 25, 2010 6:09 AM
  • Hi,

    The NullReferenceException you talk about is the exception you should focus on. The CommunicationException is, as HTanias says, an effect of an error on the other side of the channel between client and server. So if The server throws a CommunicationException, then the true error is on the client side.

    I agree with HTanias that you should catch all exceptions and wrap them in a FaultException. This way you'll get a nice exception description on both sides of the channel.


    If this reply is of help to you, please don't forget to mark it as an answer. Regards, Patriek
    Wednesday, August 25, 2010 12:21 PM
  • I am using service instance as PerCall and Concurrency mode as Multiple...

    Can some one post some sample code how to wrap all exception into Fault Exceptions and how to catch them... Is this should be done on server side or client side where we call proxy...

    Pls suggest...

     

    Thanks...

    Wednesday, August 25, 2010 2:21 PM
  • Hi htanias,

    On the service side, u need to create the errobehavior attribute class , which tells WCF that it should pass the errors to ur errorhandler. And the error handler will wrap all exception messages into FaultException("Message").And on the client side catch (FaultException) and it will not fault you channel anymore.

     Please find the below code for you problem (You can copy the complete "errorbehaviorattribute" and "errohandler classes they are in working condition).

    * Make sure you do not have includeExceptionDetailInFaults set to true as it will corrupt the channel.

     

     

     

    <serviceDebug includeExceptionDetailInFaults="true"/>  (default is false).

    --------------------------------------------------------------------------------------------------------

     

    My code below on service side will throw unhandled exception here: 

     //THIS LINE will throw AN ERROR.
     string h = yy.Title;

    SERVICE SIDE - CODE
    
     [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
     [ErrorBehavior(typeof(MyErrorHandler))]
     public class Class1 : API.Interface1
     {
    
     public string HelloWorld()
     {
      return "HelloWorld";
     }
    
     
     public API.Class2 GetClass2()
     {
      Class2 xyz = new Class2();
      Class2 yy = default(Class2);
    
      //THIS LINE will throw AN ERROR.
      string h = yy.Title;
    
    
      return xyz;
     }
    
     
     }
    
     public class MyErrorHandler : IErrorHandler
     {
      public bool HandleError(Exception error)
      {
      return true;
      }
      public void ProvideFault(Exception error,MessageVersion version, ref Message fault)
      {
      FaultException faultException = new FaultException(error.Message);
      MessageFault messageFault = faultException.CreateMessageFault( );
      fault = Message.CreateMessage(version,messageFault,faultException.Action);
      }
     }
    
    
    
     public class ErrorBehaviorAttribute : Attribute, IServiceBehavior
     {
    
     Type errorHandlerType;
    
    
     public ErrorBehaviorAttribute(Type errorHandlerType)
     {
    
      this.errorHandlerType = errorHandlerType;
    
     }
    
    
     public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
     {
    
     }
    
    
     public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase,Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
     {
    
     }
    
    
     public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
     {
    
      IErrorHandler errorHandler;
    
      errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
    
      foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
      {
    
      ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
    
      channelDispatcher.ErrorHandlers.Add(errorHandler);
    
      }
    
     }
    
     }
    
    

    Client Side code:

     

    class Program
     {
     static void Main(string[] args)
     {
    
      Class2 xyz = default(Class2);
      
      Interface1 proxy = new ChannelFactory<Interface1>(new WSHttpBinding()).CreateChannel(new EndpointAddress("http://localhost:11001/Class1"));
      try
      {
      xyz = proxy.GetClass2();
      }
      catch (FaultException ex)
      {
      
      }
      //Still able to call even after exception.
      Console.WriteLine(proxy.HelloWorld());
      Console.ReadLine();
     }
     }
    
    Thursday, August 26, 2010 5:32 PM