7

With .NET 4.5, my WCF creation using svcutil suddenly seems to break (I've been using only .NET 4.0 until very recently) ....

With the default settings I'm using to convert a pre-existing WSDL to my C# WCF proxy class:

c:> svcutil.exe /n:*,MyNamespace /out:WebService MyService.wsdl

I get this C# file created:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyService.IMyService1")]
public interface IMyService1
{
    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
    [System.ServiceModel.FaultContractAttribute(typeof(MyService.MyFault), Action="http://tempuri.org/IMyService1/IsAliveErrorInfoFault", Name="MyServiceErrorInfo", Namespace="http://schemas.datacontract.org/2004/07/MyService.Types")]
    string IsAlive();

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
    System.Threading.Tasks.Task<string> IsAliveAsync();

This doesn't work - if I try to instantiate an implemention of this interface in a ServiceHost

using (ServiceHost svcHost = new ServiceHost(typeof(MyService01Impl)))
{
    svcHost.Open();
    Console.WriteLine("Host running ...");

    Console.ReadLine();
    svcHost.Close();
}

I get this error:

Cannot have two operations in the same contract with the same name, methods 'IsAlive' and 'IsAliveAsync' in type 'MyService01Impl' violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.

Why does svcutil suddenly generate code that doesn't work??

If I use the /async keyword with svcutil, then I get the "old-style" async pattern with BeginIsAlive and EndIsAlive and things work again - but how can I tell WCF / svcutil to generate no async stuff at all?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • What command line did you use? The interface I see looks like a *proxy* interface but you are using it to create the service itself ? Having used WCF 4.5 to generate proxies (to call ebXML services no less), I can vouch that it does work and does generate both sync and async *proxy* methods for the same *contract* action. – Panagiotis Kanavos Aug 10 '15 at 08:02
  • Did you use the `/serviceContract` parameter? According to the docs, this will create classes to implement a service that complies to a specific contract. There is an example at [How to: Retrieve Metadata and Implement a Compliant Service](https://msdn.microsoft.com/en-us/library/ms735109(v=vs.110).aspx). Without this `svcutil` will produce proxy code – Panagiotis Kanavos Aug 10 '15 at 08:08
  • @PanagiotisKanavos: added my command line. I have a WSDL supplied by an external partner, and I wanted to create both a client proxy (to actually call the service), and also a "dummy" service implementation for internal use (since we cannot connect to a test system of that external partner to run the tests) – marc_s Aug 10 '15 at 10:18
  • The default is to generate proxy classes (and interfaces). You need to use /`serviceContract` to generate service classes – Panagiotis Kanavos Aug 10 '15 at 10:29
  • @PanagiotisKanavos: OK - that works for service classes - but what if I need to create a **sync** client? I used to specify *nothing* and get just sync, or `/async` and thus get both sync and async (begin/end) - but now, it seems I don't have a **sync only** option anymore - and the default of not specifying anything produces this code which doesn't work .... – marc_s Aug 10 '15 at 10:33
  • You need to use `/syncOnly` to generate a sync-only proxy. I'd avoid that though, as I typically need async for scalability reasons - lots of heavy calls to slow external partners. – Panagiotis Kanavos Aug 10 '15 at 11:25
  • @PanagiotisKanavos: excellent - thanks ! Put this together into an answer and I'll happily accept it – marc_s Aug 10 '15 at 11:26

1 Answers1

5

svcutil by default generates a proxy class with both synchronous and Task-based methods, eg:

public interface IService1
{
    ...
    string GetData(int value);
    ...    
    System.Threading.Tasks.Task<string> GetDataAsync(int value);
    ...
}

To generate a proxy with only synchronous methods, you need to use /syncOnly. This will omit the Task-based version:

public interface IService1
{
   ...
   string GetData(int value);
   ...
}

In both cases, the proxy class itself inherits from ClientBase:

public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1

Finally, the /serviceContract switch generates only the interface and DTOs necessary for generating a dummy service

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Thanks - the `synconly` option seems to be undocumented - at least I couldn't find it in the [official MSDN documentation](https://msdn.microsoft.com/en-us/library/aa347733%28v=vs.110%29.aspx) anywhere...... – marc_s Aug 10 '15 at 12:19
  • 1
    @marc_s I found it from the command-line help, just noticed it's missing from the docs too !? – Panagiotis Kanavos Aug 10 '15 at 12:30