定义“app.config”对于使用 WebHttpBinding 的 WCF 服务

发布于 2024-12-03 05:42:02 字数 1852 浏览 4 评论 0原文

我有一个 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>

突然该服务无法再启动。它在 OnStart 方法的 FileServiceHost.Open 上引发此异常:“为了使 UploadFile 操作中的请求成为流,该操作必须具有类型为 Stream 的单个参数。”

我在 app.config 中定义服务的方式一定有问题,因为当我从那里删除它时,一切正常。我在这里做错了什么?

I've got a WCF service that allows the uploading of files without using a MessageContract.

[OperationContract, WebInvoke(UriTemplate = "UploadFile?filename={filename}")]
bool UploadFile(string filename, Stream fileContents);

I'm allowed to use another parameter beside the Stream object because it's part of the UriTemplate. Since the service runs as a Managed Windows Service, I have to start the ServiceHost manually.

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();
}

With all of this, the service starts up and works just fine. However I wanted to move some of the above to the app.config file. To do this, I commented out the second line of OnStart and replaced the first line with FileServiceHost = new ServiceHost(typeof(FileService)). Then I added that info to the 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>

And suddenly the service can no longer start up. It throws this exception on FileServiceHost.Open of the OnStart method: "For request in operation UploadFile to be a stream the operation must have a single parameter whose type is Stream."

There must be something wrong with the way I'm defining the service in app.config, because when I remove it from there, everything works fine. What am I doing wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

抠脚大汉 2024-12-10 05:42:02

以下是我通过将 webHttpBinding 添加到端点行为来解决问题的方法。

behaviorConfiguration="TestBehavior" 添加到 ,然后定义 TestBehavior< /代码>如下:

<endpointBehaviors>
    <behavior name="TestBehavior">
      <webHttp />
    </behavior>
</endpointBehaviors>

Here's how I fixed the issue by adding webHttpBinding to the endpoint behavior.

Added behaviorConfiguration="TestBehavior" to <endpoint address="" binding="webHttpBinding" contract="IFile"/>, and then defined TestBehavior as follows:

<endpointBehaviors>
    <behavior name="TestBehavior">
      <webHttp />
    </behavior>
</endpointBehaviors>
深巷少女 2024-12-10 05:42:02

要在 WCF 中启用流式传输,有多个限制。其中之一是具有 Stream 类型的单个参数 (或任何其他两种类型。)

这可能意味着 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; }
}

For streaming to be enabled in WCF, there are multiple restrictions. One of them is to have a single parameter of type Stream (or any of two other types.)

This possibly means that WCF "guessed" that you were trying to stream content in your contract
and defaulted the TransferMode to Streamed (This is purely a guess. It's not what is documented. Documentation says TransferMode defaults to Buffered.)

One option would be to set the transfer mode to Buffered explicitly in XML:

<webHttpBinding>
    <binding name="MyWebBinding" transferMode="Buffered"/>
</webHttpBinding>

However, using the Buffered transfer mode, the content of the message would be entirely buffered before being sent, which is not a good thing with large files.

Another option would be to use the Streamed transfer mode. If you want to stream a file's content and provide a file name at the same time, you will have to define a custom Message class and send the file's metadata in the message headers:

[MessageContract]
public class UploadFileMessage
{
   [MessageHeader]
   public string Filename { get; set; }

   [MessageBodyMember]
   public Stream Content { get; set; }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文