views:

1047

answers:

4

I'm just getting into creating some WCF services, but I have a requirement to make them backward compatible for legacy (.NET 1.1 and 2.0) client applications.

I've managed to get the services to run correctly for 3.0 and greater clients, but when I publish the services using a basicHttpBinding endpoint (which I believe is required for the compatibility I need), the service refactors my method signatures. e.g.

public bool MethodToReturnTrue(string seedValue);

appears to the client apps as

public void MethodToReturnTrue(string seedValue, out bool result, out bool MethodToReturnTrueResultSpecified);

I've tried every configuration parameter I can think of in the app.config for my self-hosting console app, but I can't seem to make this function as expected. I suppose this might lead to the fact that my expectations are flawed, but I'd be surprised that a WCF service is incapable of handling a bool return type to a down-level client.

My current app.config looks like this.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>  
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="MyServiceTypeBehaviors" Name="MyCompany.Services.CentreService.CentreService">
        <clear />
        <endpoint address="http://localhost:8080/CSMEX"    binding="basicHttpBinding" bindingConfiguration="" contract="IMetadataExchange" />
        <endpoint address="http://localhost:8080/CentreService" binding="basicHttpBinding" bindingName="Compatible" name="basicEndpoint" contract="MyCompany.Services.CentreService.ICentreService" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors" >
            <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Can anyone advise, please?

+2  A: 

Ah, this is killing me! I did this at work about 3 months ago, and now I can't remember all the details.

I do remember, however, that you need basicHttpBinding, and you can't use the new serializer (which is the default); you have to use the "old" XmlSerializer.

Unfortunately, I don't work at the place where I did this anymore, so I can't go look at the code. I'll call my boss and see what I can dig up.

Esteban Araya
A: 

@Esteban

Thanks for the response. If you can dig something up I'd really appreciate it. Otherwise, I now at least have a place to start (XmlSerializer)

ZombieSheep
+1  A: 

OK, we needed to resolve this issue in the short term, and so we came up with the idea of a "interop", or compatibility layer.

Baiscally, all we did was added a traditional ASMX web service to the project, and called the WCF service from that using native WCF calls. We were then able to return the appropriate types back to the client applications without a significant amount of re-factoring work. I know it was a hacky solution, but it was the best option we had with such a large legacy code-base. And the added bonus is that it actually works surprisingly well. :)

ZombieSheep
A: 

You do have to use the XmlSerializer. For example:

[ServiceContract(Namespace="CentreServiceNamespace")]
[XmlSerializerFormat(Style=OperationFormatStyle.Document, SupportFaults=true, Use=OperationFormatUse.Literal)]
public interface ICentreService {
    [OperationContract(Action="CentreServiceNamespace/MethodToReturnTrue")]
    bool MethodToReturnTrue(string seedValue);
}

You have to manually set the operation action name because the auto-generated WCF name is constructed differently from the ASMX action name (WCF includes the interface name as well, ASMX does not).

Any data contracts you use should be decorated with [XmlType] rather than [DataContract].

Your config file should not need to change.

Christian Hayter