WCF:使用带有消息契约的流式传输
Posted
技术标签:
【中文标题】WCF:使用带有消息契约的流式传输【英文标题】:WCF: using streaming with Message Contracts 【发布时间】:2010-11-23 07:34:39 【问题描述】:我正在尝试将 WCF 流与消息契约一起使用,因为除了流本身之外我还需要其他参数。
基本上我正在创建一个文件上传和下载服务,上面有一些额外的逻辑。
不幸的是,当我尝试从浏览器点击服务以检查一切是否正常时,我收到以下错误:
“/”应用程序中的服务器错误。 合同“IFileTransferService”中的“UploadFile”操作使用具有 SOAP 标头的 MessageContract。 None MessageVersion 不支持 SOAP 标头。
不幸的是,谷歌搜索并没有产生任何对我有帮助的重要结果。你们能帮帮我吗?这里是服务的详细信息(由于空间原因,我已经删除了下载部分)。
[ServiceContract(Namespace = "http://www.acme.org/2009/04")]
public interface IFileTransferService
[OperationContract(Action = "UploadFile")]
void UploadFile(FileUploadMessage request);
[MessageContract]
public class FileUploadMessage
[MessageHeader(MustUnderstand = true)]
public FileMetaData Metadata get; set;
[MessageBodyMember(Order = 1)]
public Stream FileByteStream get; set;
[DataContract(Namespace = "http://schemas.acme.org/2009/04")]
public class FileMetaData
[DataMember(Name="FileType", Order=0, IsRequired=true)]
public FileTypeEnum fileType;
[DataMember(Name="localFilename", Order=1, IsRequired=false)]
public string localFileName;
[DataMember(Name = "remoteFilename", Order = 2, IsRequired = false)]
public string remoteFileName;
我尝试同时使用 basichttpbinding 和 customhttp 绑定,但效果不佳:
<customBinding>
<binding name="customHttpBindingStream">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport transferMode="Streamed" maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
更新:在线阅读文档,似乎确实可以使用 MessageContracts 进行流式传输。例如参考 MSDN (Large Data and Streaming):
流传输的编程模型
流的编程模型是 直截了当。用于接收 流数据,指定操作 具有单个 Stream 的合约 键入的输入参数。用于返回 流数据,返回一个 Stream 参考。 [...]这条规则类似 适用于消息合约。如图所示 在以下消息合同中,您 只能有一个主体成员 您的消息合同是 溪流。如果你想交流 附加信息 流,此信息必须是 在消息头中携带。这 消息正文是专门保留的 用于流内容。
[MessageContract]
public class UploadStreamMessage
[MessageHeader]
public string appRef;
[MessageBodyMember]
public Stream data;
我还看到人们完成文件上传和下载服务的博客文章与我试图放在一起的内容非常相似(例如here)。
更新 2 我尝试创建一个小型控制台并使用 basicHttpBinding 自行托管服务,它的工作原理就像一个魅力。我开始相信问题可能出在 IIS 上。有什么想法吗?
更新 3 请参阅我自己的答案。
【问题讨论】:
我相信Order = 1
在MessageBodyMember
属性中是多余的,因为你只有一个body 元素
【参考方案1】:
我终于发现了错误:它与 Soap 版本、流等无关...我只是拼错了我自己的服务的名称 (!),使用 FileTransfer
而不是 FileTransferService
。
最后 basicHttpBinding 非常好,我不需要求助于自定义绑定。
原始(坏)版本:
<service
behaviorConfiguration="serviceBehavior"
name="Acme.Service.FileTransfer">
<endpoint address=""
name="basicHttpStream"
binding="basicHttpBinding"
bindingConfiguration="httpLargeMessageStream"
contract="Acme.Service.IFileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
新(固定)版本:
<service
behaviorConfiguration="serviceBehavior"
name="Acme.Service.FileTransferService">
<endpoint address=""
name="basicHttpStream"
binding="basicHttpBinding"
bindingConfiguration="httpLargeMessageStream"
contract="Acme.Service.IFileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
我仍然不能说错误消息对理解这里发生的事情有任何帮助....
如果您对整个服务感兴趣,可以通过以下链接在我的博客中找到更多详细信息:File Transfer with WCF
【讨论】:
【参考方案2】:您是否需要在请求和响应中都进行流式传输(即传输大量数据)?或者只是响应(通常:下载文件或大型数据集)?
如果您只需要响应,您应该尝试将传输模式设置为“StreamedResponse”:
<customBinding>
<binding name="customHttpBindingStream">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport transferMode="StreamedResponse"
maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
“流式传输”设置将双向流式传输 - 发送到服务器的请求以及来自服务器的响应都将被流式传输。通常情况下,这不是理想的情况。
马克
【讨论】:
嗨,Marc,正如我在问题中提到的,我正在创建一个允许上传和下载文件的文件服务。因此,我确实需要能够双向流式传输。您认为这与我遇到的错误有关吗? 不确定 - 我以前从未见过流式传输与消息合约的组合.....而且我见过只有从服务器下载很大的情况(下载文件)和设置TransferMode 到 StreamedResponse 的帮助 如果你只使用 DataContract(没有 Message Contract 部分),它是否工作 - 只是为了看看,为了测试 是的,它使用 Stream 对象或 DataContract 作为参数。 马克,感谢您的跟进。感谢您为帮助我所做的努力。但是,似乎流 + MessageContracts 应该可以工作。查看我对原始问题的更新。【参考方案3】:使用“WCF 数据服务”模板而不是“WCF 服务”模板生成 svc 文件后出现错误。更正服务主机文件问题已解决。
【讨论】:
以上是关于WCF:使用带有消息契约的流式传输的主要内容,如果未能解决你的问题,请参考以下文章