简体   繁体   中英

Why does refactoring a server interface break the client proxy contract?

I have an existing WCF web service which uses an interface something like

 [ServiceContract]
  public interface IMyWebServices
  {    
    [OperationContract]
    bool MethodA();

    [OperationContract]
    bool MethodB();
  }

and then the implementation...

public class MyWebServices : IMyWebServices
{
  public bool MethodA(){...}
  public bool MethodB(){...}
 }

I have a client where I generated a proxy and all is good.

Later, the number or operations in this service grows. So with the implementation, I factored all the code into other classes and injected these into the main class.

[ServiceContract]
   public interface IMyWebServices : IServices1, IServices2
   {            
   }

   [ServiceContract]
   public interface IServices1
   {            
     [OperationContract]
      bool MethodA();
   }

   [ServiceContract]
   public interface IServices2
   {            
     [OperationContract]
     bool MethodB();
   }

   public class MyWebServices : IMyWebServices
    {
      private IServices1 _s1;
      private IServices2 _s2;
      public MyWebServices(IServices1, s1, IServices2, s2)
      {
          _s1 = s1;
          _s2 = s2;
      }

      public bool MethodA()
      {
          return _s1.MethodA()
      }
      public bool MethodB()
      {
            return _s2.MethodB()
      }
     }

The problem now is that an existing deployed client (so no proxy regeneration) will now get an error if the new service is deployed. Event though the contract is exactly the same I get an error along the lines of

...cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, eg Message, Transport, None).

So it appear you cannot do any refactoring of the server side interfaces.

Is there any way around this (for future refactoring), or is this just something we have to live with using WCF (so we need to regenerate the proxy of any exiting clients)?

Svcutil generated service client proxy is based on service metadata. So modifying service-side signatures can lead to new wsdl and broken clients (based on old service metadata). This is one more reason to not use (auto-)generated client proxy code. With some little effort you can get your own code (more managable) based on your service contracts (just share it for service clients in separate assembly) and ChannelFactory(...).CreateChannel(). This way will help you. Service contract refactoring will have client side code reflection.

WSHttpBinding myBinding = new WSHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/MyService.svc");
ChannelFactory<IMyService> myChannelFactory = new ChannelFactory<IMyService>(myBinding, myEndpoint);
IMyService instance = myChannelFactory.CreateChannel();            
var result = instance.MyMethod(...);

or

ChannelFactory<IMyService> myChannelFactory = new ChannelFactory<IMyService>("WSHttpBinding_IMyService");

where "WSHttpBinding_IMyService" is client binding configuration name:

<system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name=”WSHttpBinding_IMyService” />
                </wsHttpBinding>
            </bindings>
            <client>
                 <endpoint address=”http://localhost:8000/MyService.svc”
                                  binding=”wsHttpBinding”
                                  bindingConfiguration=”WSHttpBinding_IMyService”
                                  contract=”MyService.IMyService”
                                  name=”WSHttpBinding_IMyService”>
                 </endpoint>
             </client>
  </system.serviceModel>

With some extra work you can even call service methods asynchronously by knowing and using simple synchronous service interface! (You can find universal service client code, for example, here . I have my own and more simple implementation, I will share it soon.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM