20

我正在尝试将 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(大数据和流):

流传输的编程模型

流的编程模型很简单。要接收流数据,请指定具有单个 Stream 类型输入参数的操作协定。要返回流数据,请返回 Stream 引用。[...]这条规则同样适用于消息合约。如以下消息协定所示,您的消息协定中只能有一个主体成员,即流。如果您想与流通信附加信息,则此信息必须是在消息头中携带的。消息正文专为流内容保留。

[MessageContract]
public class UploadStreamMessage
{
   [MessageHeader]
   public string appRef;
   [MessageBodyMember]
   public Stream data;
} 

我还看到人们完成文件上传和下载服务的博客文章与我试图放在一起的内容非常相似(例如这里)。

更新 2 我尝试创建一个小型控制台并使用 basicHttpBinding 自行托管服务,它的工作原理就像一个魅力。我开始相信问题可能出在 IIS 上。任何想法?

更新 3 查看我自己的答案。

4

3 回答 3

8

我终于发现了错误:它与 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>

我仍然不能说错误消息有助于理解这里发生的事情......

如果您对整个服务感兴趣,可以在我的博客上的以下链接中找到更多详细信息:使用 WCF 进行文件传输

于 2009-08-28T10:48:22.090 回答
2

您是否在请求和响应中都需要流式传输(即传输大量数据)?或者只是响应(通常:下载文件或大型数据集)?

如果您只需要响应,则应尝试将传输模式设置为“StreamedResponse”:

<customBinding>
    <binding name="customHttpBindingStream">
        <textMessageEncoding messageVersion="Soap12" />
        <httpTransport transferMode="StreamedResponse" 
                       maxReceivedMessageSize="2147483647"/>
    </binding>
</customBinding>

“流式传输”设置将双向流式传输 - 发送到服务器的请求以及来自服务器的响应都将被流式传输。通常情况下,这不是理想的情况。

马克

于 2009-08-27T14:08:15.397 回答
0

使用“WCF 数据服务”模板而不是“WCF 服务”模板生成 svc 文件后出现错误。更正服务主机文件问题已解决。

于 2012-07-06T11:33:47.127 回答