.NET 4.5 中的 WCF / svcutil 默认生成无法使用的代码

WCF / svcutil in .NET 4.5 generates unusable code by default

使用 .NET 4.5,我使用 svcutil 创建的 WCF 似乎突然中断(直到最近我一直只使用 .NET 4.0)....

我使用默认设置将预先存在的 WSDL 转换为我的 C# WCF 代理 class:

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

我创建了这个 C# 文件:

[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();

这不起作用 - 如果我尝试在 ServiceHost

中实例化此接口的实现
using (ServiceHost svcHost = new ServiceHost(typeof(MyService01Impl)))
{
    svcHost.Open();
    Console.WriteLine("Host running ...");

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

我收到这个错误:

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.

为什么 svcutil 突然生成不起作用的代码??

如果我将 /async 关键字与 svcutil 一起使用,那么我将使用 BeginIsAliveEndIsAlive 获得 "old-style" 异步模式,然后事情又会发生 -但是我怎么能告诉 WCF / svcutil 生成 no async 东西呢?

svcutil 默认生成一个代理 class 同时使用同步和基于任务的方法,例如:

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

要生成仅具有同步方法的代理,您需要使用 /syncOnly。这将省略基于任务的版本:

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

在这两种情况下,代理 class 本身继承自 ClientBase:

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

最后,/serviceContract 开关仅生成生成虚拟服务所需的接口和 DTO