使用流进行最简单的 RESTful WCF 服务调用

发布于 2024-11-03 18:48:08 字数 2843 浏览 3 评论 0原文

我想创建一个具有以下属性的 Web 服务:

  • 它使用 WCF 和 .NET 4.0
  • 它托管在 IIS7 中
  • 它是 RESTful
    • 可以保留收集和处理 WebFaultException 等的默认输出行为
  • 它有一个调用
    • 吃掉潜在巨大二进制文件的赤裸裸的 HTTP POST(最好不要保存在内存中!)
    • 接受 Stream 作为输入
    • 输出流
    • 使用 UriTemplate 进行匹配(很快就会有更多调用)
    • 希望流完全是原始的,并且让 IIS 或 WCF 尝试通过以任何方式处理内容类型来实现智能

问题是 IIS 和/或 WCF 不断干扰 Content-Type,

415 Cannot process the message because the content type '...' was not the expected type 'text/xml; charset=utf-8'

无论如何都 坚持返回内容类型是。你能发现我在下面犯的任何错误吗?

[ServiceContract]
public interface IRenderService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/render", BodyStyle = WebMessageBodyStyle.Bare)]
    Stream Render(Stream input);
}

使用 Web.config 中的以下片段:

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="500000000" />
</system.web>
<system.serviceModel>
    <bindings>
        <webHttpBinding>
            <binding
              name="FileStreamConfiguration"
              transferMode="Streamed"
              maxReceivedMessageSize="500000000"
              maxBufferSize="500000000"
              openTimeout="00:25:00"
              closeTimeout="00:25:00"
              sendTimeout="00:25:00"
              receiveTimeout="00:25:00" />
        </webHttpBinding>
    </bindings>
    <services>
        <service name="RenderService" behaviorConfiguration="RenderServiceBehavior">
            <endpoint address="" binding="webHttpBinding" contract="RenderServer.IRenderService" bindingConfiguration="FileStreamConfiguration" behaviorConfiguration="RenderEndpointBehaviour" >
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="RenderServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="RenderEndpointBehaviour">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

我希望始终获取 HTTP POST 正文的原始内容,并在我认为必要时手动从 WebOperationContext.Current.IncomingRequest 获取标头,以及 IIS/WCF除了解析请求并将其发送到我的代码之外,应该完全忽略请求的所有方面。我将使用 WebOperationContext.Current.OutgoingResponse 来设置我认为合适的输出的各个方面,也可以手动设置。

I want to make a web service with the following properties:

  • It uses WCF and .NET 4.0
  • It is hosted in IIS7
  • It is RESTful
    • It's okay to keep the default output behaviour of collecting and handling WebFaultExceptions etc
  • It has a single call that
    • eats naked HTTP POST of potentially huge binary files (should preferably not be kept in memory!)
    • accepts a Stream as an input
    • outputs a Stream
    • uses an UriTemplate for matching (there will be more calls soon)
    • wants the streams to be completely raw and NOT have IIS or WCF try to be smart by handling the content type in any way

The problem is that IIS and/or WCF keep interfering regarding the Content-Type, insisting on returning

415 Cannot process the message because the content type '...' was not the expected type 'text/xml; charset=utf-8'

no matter what the content type was. Can you spot any errors I have made below?

[ServiceContract]
public interface IRenderService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/render", BodyStyle = WebMessageBodyStyle.Bare)]
    Stream Render(Stream input);
}

With the following snippets from Web.config:

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="500000000" />
</system.web>
<system.serviceModel>
    <bindings>
        <webHttpBinding>
            <binding
              name="FileStreamConfiguration"
              transferMode="Streamed"
              maxReceivedMessageSize="500000000"
              maxBufferSize="500000000"
              openTimeout="00:25:00"
              closeTimeout="00:25:00"
              sendTimeout="00:25:00"
              receiveTimeout="00:25:00" />
        </webHttpBinding>
    </bindings>
    <services>
        <service name="RenderService" behaviorConfiguration="RenderServiceBehavior">
            <endpoint address="" binding="webHttpBinding" contract="RenderServer.IRenderService" bindingConfiguration="FileStreamConfiguration" behaviorConfiguration="RenderEndpointBehaviour" >
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="RenderServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="RenderEndpointBehaviour">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

I want to always get the raw contents of the HTTP POST body, and fetch headers from WebOperationContext.Current.IncomingRequest manually if I deem that necessary, and IIS/WCF should completely ignore all aspects of the request besides parsing it and sending it to my code. I'll use WebOperationContext.Current.OutgoingResponse to set aspects of the output as I see fit, also manually.

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

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

发布评论

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

评论(1

我为君王 2024-11-10 18:48:08

使用新的 WCF Web API 库可以轻松实现这一点。请参阅 http://wcf.codeplex.com 我的博客上有一个示例,一旦通电我将发布该示例返回:-)

界面如下所示,

[ServiceContract]
public interface IRenderService{

    [WebInvoke(Method = "POST", UriTemplate = "/render")]
    HttpResponseMessage Render(HttpRequestMessage input);
}

This is so easy to do with the new WCF Web API library. See http://wcf.codeplex.com I have a sample on my blog which I will post once the power comes back on :-)

The interface looks like this,

[ServiceContract]
public interface IRenderService{

    [WebInvoke(Method = "POST", UriTemplate = "/render")]
    HttpResponseMessage Render(HttpRequestMessage input);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文