无法为Web应用程序引用BCL.Async序列化任务`1

Ste*_*lom 2 c# wcf asynchronous asp.net-mvc-3

我们最近在测试域中部署了一个新开发的预编译服务,并收到以下错误:

Type 'System.Threading.Tasks.Task`1[Domain.Infrastructure.Contracts.Configuration.DomainServices]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types. 
Run Code Online (Sandbox Code Playgroud)

服务器是运行.NET 4.0的Windows 2008R2.

关于此问题有一些Stack Overflow问题,但大多数问题似乎都是指Async的CTP版本.显然,您必须在服务器上安装.NET 4.5才能使用此代码.

随着BCL.Async NuGet包的发布,这种情况是否发生了变化?

我的印象是,使用Async编译器编译并包含NuGet的BCL库的代码具有在.NET 4环境中运行所需的一切.

是否仍然需要将服务器上的.NET运行时升级到4.5?

编辑:提供堆栈跟踪:

[InvalidDataContractException: Type 'System.Threading.Tasks.Task`1[Domain.Infrastructure.Contracts.Configuration.DomainServices]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.]
System.Runtime.Serialization.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type) +1184850
System.Runtime.Serialization.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) +787
System.Runtime.Serialization.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) +117
System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(Type type) +85
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory) +48
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory) +708
System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory) +570
System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription operation, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy) +308
System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch) +69
System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) +120
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +4250
System.ServiceModel.ServiceHostBase.InitializeRuntime() +82
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +64
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +255
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +1172

[ServiceActivationException: The service '/Services/Binary/Endpoint.svc' cannot be activated due to an exception during compilation.  The exception message is: Type 'System.Threading.Tasks.Task`1[Domain.Infrastructure.Contracts.Configuration.DomainServices]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types..]
System.Runtime.AsyncResult.End(IAsyncResult result) +901504
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +178638
System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +107
Run Code Online (Sandbox Code Playgroud)

Ada*_*ras 8

好的,我将在这里做一个很好的猜测,你正在尝试公开一个返回a的异步WCF操作Task<Domain.Infrastructure.Contracts.Configuration.DomainServices>.虽然Microsoft.Bcl.Async将允许您编译使用任务的代码,但它不会向WCF提供允许您在服务中使用任务的.NET Framework 4.5更改.

话虽这么说,你仍然可以使用异步编程模型将异步方法暴露给WCF,同时仍然使用TPL编写代码.为此,您必须使用APM开始/结束方法包装该方法.像这样的东西:

[ServiceContractAttribute]
public interface ISampleService
{
    [OperationContractAttribute]
    string SampleMethod();

    [OperationContractAttribute(AsyncPattern = true)]
    IAsyncResult BeginSampleMethod(AsyncCallback callback, object asyncState);

    string EndSampleMethod(IAsyncResult result);
}

public class SampleService : ISampleService
{
    // the async method needs to be private so that WCF doesn't try to
    // understand its return type of Task<string>
    private async Task<string> SampleMethodAsync()
    {
        // perform your async operation here
    }

    public string SampleMethod()
    {
        return this.SampleMethodAsync().Result;
    }

    public IAsyncResult BeginSampleMethod(AsyncCallback callback, object asyncState)
    {
        var task = this.SampleMethodAsync();
        if (callback != null)
        {
            task.ContinueWith(_ => callback(task));
        }

        return task;
    }

    public string EndSampleMethod(IAsyncResult result)
    {
        return ((Task<string>)result).Result;
    }
}
Run Code Online (Sandbox Code Playgroud)