C# WCF:将流与消息协定结合使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1339857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:19:34  来源:igfitidea点击:

WCF: using streaming with Message Contracts

c#.netwcfwcf-bindingwcf-configuration

提问by Stefano Ricciardi

I am trying to use the WCF streaming with Message Contracts, because I need additional parameters beside the stream itself.

我正在尝试将 WCF 流与消息协定一起使用,因为除了流本身之外我还需要其他参数。

Basically I am creating a file upload and download service, with some additional logic on top.

基本上,我正在创建一个文件上传和下载服务,并在顶部添加一些额外的逻辑。

Unfortunately, when I try to hit the service from the browser to check that everything is all right, I get the following error:

不幸的是,当我尝试从浏览器访问该服务以检查一切是否正常时,出现以下错误:

Server Error in '/' Application. Operation 'UploadFile' in contract 'IFileTransferService' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion.

“/”应用程序中的服务器错误。合同“IFileTransferService”中的“UploadFile”操作使用具有 SOAP 标头的 MessageContract。None MessageVersion 不支持 SOAP 标头。

Unfortunately googling for it did not yield any significant result that helped me. Can you guys have help me out? Here the details of the service (I have removed the download part for reason of space).

不幸的是,谷歌搜索并没有产生任何对我有帮助的重要结果。你们能帮我吗?这里是服务的详细信息(由于空间原因,我已经删除了下载部分)。

[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;
}

I have tried to use both basichttpbinding and a customhttp binding with not positive effect:

我尝试同时使用 basichttpbinding 和 customhttp binding,但效果不佳:

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

UPDATE: reading the documentation online it seems that streaming with MessageContracts should indeed be possible. Refer for example to MSDN (Large Data and Streaming):

更新:在线阅读文档似乎确实可以使用 MessageContracts 进行流式传输。例如参考 MSDN(大数据和流):

Programming Model for Streamed Transfers

The programming model for streaming is straightforward. For receiving streamed data, specify an operation contract that has a single Stream typed input parameter. For returning streamed data, return a Stream reference. [...] This rule similarly applies to message contracts. As shown in the following message contract, you can have only a single body member in your message contract that is a stream. If you want to communicate additional information with the stream, this information must be a carried in message headers. The message body is exclusively reserved for the stream content.

流式传输的编程模型

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

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

I have also seen blog posts from people accomplishing services of file upload and download very similar to what I am trying to put together (for example here).

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

UPDATE 2I have tried creating a small console and self hosting the service with a basicHttpBinding and there it works like a charm. I am starting to believe that the problem might be the hosting on IIS. Any idea?

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

UPDATE 3See my own answer.

更新 3请参阅我自己的答案。

采纳答案by Stefano Ricciardi

I finally found out what was the error: it had nothing to do with Soap versions, streams, etc... I just mispelled the name of my own service (!), using FileTransferinstead of FileTransferService.

我终于发现了错误是什么:它与 Soap 版本、流等无关......我只是拼错了我自己的服务的名称(!),使用FileTransfer而不是FileTransferService.

In the end basicHttpBinding was perfectly fine, I didn't need to resort to a custom binding.

最后 basicHttpBinding 非常好,我不需要求助于自定义绑定。

Original (bad) version:

原始(坏)版本:

<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>

New (fixed) version:

新(固定)版本:

<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>

Still I can't say that the error message was helpful in any way to understand what was going on here....

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

If you are interested in the whole service, you can find more details on my blog at the following link: File Transfer with WCF

如果您对整个服务感兴趣,可以在我的博客上的以下链接中找到更多详细信息:File Transfer with WCF

回答by marc_s

Do you need streaming (i.e. transfer of humonguous data amounts) both on the request and response? Or just on the response (typically: downloading a file or large data set)?

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

If you need only on the response, you should try to set the transfermode to "StreamedResponse":

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

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

The "Streamed" setting will stream both ways - both the request going to the server, as well as the response from the server, will be streamed. More often than not, that's not the ideal scenario.

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

Marc

马克

回答by fhrn71

I got the error after using the 'WCF Data Service' template to generate the svc file instead of the 'WCF Service' template. Correcting the service host file the issue was solved.

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