我有一个WCF服务,允许在不使用MessageContract的情况下上传文件。
[OperationContract, WebInvoke(UriTemplate = "UploadFile?filename={filename}")]
bool UploadFile(string filename, Stream fileContents);
我被允许在Stream对象旁边使用另一个参数,因为它是UriTemplate的一部分。由于该服务作为托管Windows服务运行,因此我必须手动启动ServiceHost。
protected override void OnStart(string[] args)
{
FileServiceHost = new ServiceHost(typeof(FileService), new Uri("http://" + Environment.MachineName + ":8000/FileService"));
FileServiceHost.AddServiceEndpoint(typeof(IFile), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
FileServiceHost.Open();
}
通过所有这些,服务启动并运行正常。但是我想将上面的一些内容移到app.config文件中。为此,我注释掉OnStart
的第二行,并将第一行替换为FileServiceHost = new ServiceHost(typeof(FileService))
。然后我将该信息添加到app.config ...
<system.serviceModel>
<services>
<service name="Test.Server.FileService" behaviorConfiguration="DefaultBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/FileService"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="IFile"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
突然间,服务无法启动。它在FileServiceHost.Open
方法的OnStart
上抛出此异常:“对于操作中的请求,UploadFile为流,操作必须具有一个类型为Stream的参数。”
我在app.config中定义服务的方式肯定有问题,因为当我从那里删除它时,一切正常。我在这里做错了什么?
答案 0 :(得分:2)
以下是我通过将webHttpBinding
添加到端点行为来解决问题的方法。
将behaviorConfiguration="TestBehavior"
添加到<endpoint address="" binding="webHttpBinding" contract="IFile"/>
,然后按如下方式定义TestBehavior
:
<endpointBehaviors>
<behavior name="TestBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
答案 1 :(得分:1)
要在WCF中启用流式传输,有多种限制。其中之一是拥有Stream
(or any of two other types类型的单个参数。)
这可能意味着WCF“猜到”您试图在合同中传输内容
并将TransferMode
默认为Streamed
(这纯粹是猜测。这不是记录的内容。文档说TransferMode
默认为Buffered
。)
一种选择是在XML中明确地将传输模式设置为Buffered
:
<webHttpBinding>
<binding name="MyWebBinding" transferMode="Buffered"/>
</webHttpBinding>
但是,使用Buffered
传输模式,邮件的内容在发送之前将完全缓冲,这对于大文件来说不是一件好事。
另一种选择是使用Streamed
传输模式。如果要同时传输文件的内容并提供文件名,则必须定义自定义Message
类并在邮件头中发送文件的元数据:
[MessageContract]
public class UploadFileMessage
{
[MessageHeader]
public string Filename { get; set; }
[MessageBodyMember]
public Stream Content { get; set; }
}