Search code examples
wcfunit-testingmetadatawcf-bindingnamed-pipes

How do you configure WCF to support FaultContracts where both the host and client are in the same process using a net.pipe?


I'm trying to create an in-process unit test for my service to client interactions using net.pipe binding. Like a good WCF service it uses FaultContractAttribute on service operations to expose possible faults (wrapped exceptions) to metadata. I would like to have the client and service endpoints configured thru XML (App.config). However, whenever a fault is thrown, it's just a CommunicationException "pipe has closed", and not the typed Fault I was expecting.

System.ServiceModel.CommunicationException: There was an error reading from the pipe: The pipe has been ended. (109, 0x6d). 

I tried Adding IMetadataExchange endpoint for net.pipe, but that didn't work. I also tried . Which being on Vista required me to netsh the ACL for the http endpoint. That too did not work.

The custom exception class:

public class ValidationException : ApplicationException { }

This is the latest attempt at a config, but it pumps out "The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service"

Any Links to examples or recommendations for how to get this done would be appreciated.

<system.serviceModel>

  <client>
    <endpoint name="Client"
              contract="IService"
              address="net.pipe://localhost/ServiceTest/"
              binding="netNamedPipeBinding"
              bindingConfiguration="netPipeBindingConfig" />
  </client>

  <services>
    <service
      name="Service"
      behaviorConfiguration="ServiceFaults">
      <host>
        <baseAddresses>
          <add baseAddress="net.pipe://localhost/ServiceTest/"/>
          <add baseAddress="http://localhost/ServiceTest/"/>
        </baseAddresses>
      </host>
      <endpoint
        address=""
        binding="netNamedPipeBinding"
        bindingConfiguration="netPipeBindingConfig"

        name="ServicePipe"
        contract="IService" />
      <endpoint
        address="MEX"
        binding="mexNamedPipeBinding"
        bindingConfiguration="mexNetPipeBindingConfig"
        name="MexUserServicePipe"
        contract="IMetadataExchange" />
    </service>
  </services>

  <bindings>
    <netNamedPipeBinding>
      <binding name="netPipeBindingConfig"
               closeTimeout="00:30:00"
               sendTimeout="00:30:00" />
    </netNamedPipeBinding>
    <mexNamedPipeBinding>
      <binding name="mexNetPipeBindingConfig"></binding>
    </mexNamedPipeBinding>
  </bindings>

  <behaviors>
    <serviceBehaviors>
      <behavior name="ServiceFaults">
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
      <behavior name="MEX">
        <serviceMetadata 
          httpGetEnabled="true"
          httpGetUrl="http://localhost/ServiceTest/MEX"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>

</system.serviceModel>


Solution

  • If the ValidationException class you describe above is the class you are using for faults, it may be the source of your problem. You should derive your fault exceptions from FaultException because it is Serializable. ApplicationException is not.

    Wagner is right, you need to decorate your operation definition with a FaultContract attribute giving it the type of your contract. You should also to decorate your FaultContract with DataContract and DataMember attributes as well.