WCF:通过消息契约使用流式传输
我正在尝试将 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 看我自己的回答。
I am trying to use the WCF streaming with Message Contracts, because I need additional parameters beside the stream itself.
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.
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:
<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):
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.
[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 2
I 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?
UPDATE 3
See my own answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我终于发现了错误所在:它与 Soap 版本、流等无关...我只是拼错了我自己的服务名称(!),使用
FileTransfer
而不是文件传输服务
。最后 basicHttpBinding 非常好,我不需要诉诸自定义绑定。
原始(坏)版本:
新(修复)版本:
不过我不能说错误消息对理解这里发生的事情有任何帮助......
如果您对整个服务感兴趣,您可以找到有关我的博客的更多详细信息,请访问以下链接:使用 WCF 进行文件传输
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
FileTransfer
instead ofFileTransferService
.In the end basicHttpBinding was perfectly fine, I didn't need to resort to a custom binding.
Original (bad) version:
New (fixed) version:
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
您是否需要在请求和响应上进行流式传输(即传输大量数据)?或者只是响应(通常:下载文件或大型数据集)?
如果您只需要响应,则应尝试将传输模式设置为“StreamedResponse”:
“Streamed”设置将双向传输 - 发送到服务器的请求以及来自服务器的响应都将被传输。通常,这不是理想的情况。
马克
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":
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.
Marc
使用“WCF 数据服务”模板而不是“WCF 服务”模板生成 svc 文件后出现错误。更正服务主机文件,问题已解决。
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.