views:

395

answers:

3

Is it possible for multiple wcf services to implement the same service contract interface?

What I want to do is allow for a test service to be interchangeable for the real service, and to specify which service to be used in the configuration file.

For example:

[ServiceContract]
public interface IUselessService  
{  
  [OperationContract]   
  string GetData(int value);   
}  

Test implementation

public class TestService : IUselessService  
{  
  public string GetData(int value)  
  {  
    return "This is a test";   
  }  
}  

Real class

public class RealService : IUselessService  
{  
  public string GetData(int value)  
  {  
    return string.Format("You entered: {0}", value);  
  }  
}
+3  A: 

Yes, it's not only possible, it is explicitly within the design intentions of service contract interfaces.

John Weldon
I've tried doing this, but get a configuration error.I'm probably doing it wrong.I have each of the service classes in their own .svc and .svc.cs files.Then I specify the service name I want in: <service behaviorConfiguration="WcfService1.Service1Behavior" name="WcfService1.RealService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="testBasicHttpBinding" contract="WcfService1.IUselessService"> </endpoint>Then I change the name attribute of the service XML element, and hen I get a runtime error that the original service has no endpoints.
Andrew Wu
I think you want to refer to the interface name in your config, rather than the real service. Make sure both (all) implementations use the same interface.
John Weldon
To be able to use the same interface, the interface must not only have the same signature (the same parameters). It must be the same in .NET type system. To make so, the definition of the Interface must be placed in a strong signed assembly and placed in GAC with GACUtil -i MyInterface.dll. Then in both projects one have to reference this assembly.
Oleg
good comment Oleg!
John Weldon
+2  A: 

If you define IUselessService interface inside a separate assembly and place this in GAC. This assembly should don't implement anything only define IUselessService interface and some other types which use needs as a parameters of IUselessService.

Both TestService and RealService should implement the same IUselessService interface. I mean you should create two additional project for each service, then TestService and RealService will have no type conflicts.

Oleg
A: 

Thanks guys for your answers. I have a solution now that works for me, without putting the interface in a separate assembly and in the GAC. I'm not looking at using the interface for other projects, just using the same interface for multiple services in the same project.

What I was trying to do was make the change between RealService and TestService in the configuration file of the WCF service, so the client would not know the difference (the client would not have to change its configuration to point to a different .svc file). I'm not sure this is possible, or it least if it is, it is definitely not straightfoward.

What I am doing now is just specifying both services in the configuration file of the WCF service, and then I point the client to one or the other based on which service I want. Since this WCF service is for internal use only and we have control of both the client and the service, it is not a bad tradeoff. This solution is probably more explicit in its intentions anyways.

Here is the snippet of the configuration file:

<services>
      <service behaviorConfiguration="WcfService1.Service1Behavior"
               name="WcfService1.TestService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="testBasicHttpBinding" 
          contract="WcfService1.IUselessService">              
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
      <service behaviorConfiguration="WcfService1.Service1Behavior"
               name="WcfService1.RealService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="testBasicHttpBinding"
         contract="WcfService1.IUselessService">             
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
Andrew Wu