如果处理了流,则带有Stream参数的WCF REST服务将抛出400

时间:2018-04-06 04:51:37

标签: c# web-services wcf stream wcf-rest

我有一个非常笨拙的行为的WCF REST服务。如果我使用普通参数,比如int和我之后抛出任何类型的WebFaultException,我都没有任何问题。作为一个例子,我可以抛出403.但是,如果我有一个Stream作为参数,我关闭和/或处理流并在以后任何时候抛出WebFaultException,它总是抛出400 Bad Request而不是其他任何东西。 / p>

这是配置:

<system.serviceModel>
<behaviors>
  <endpointBehaviors>
    <behavior name="web">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="MyServiceBehaviour">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service name="MyService" behaviorConfiguration="MyServiceBehaviour">
    <endpoint binding="webHttpBinding" name="webHttpEndpoint" contract="IMyService" behaviorConfiguration="web"/>
    <endpoint address="mex" binding="mexHttpBinding" name="mexHttpEndpoint" contract="IMetadataExchange"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:9009/MyService"/>
      </baseAddresses>
    </host>
  </service>
</services>

这里是IMyInterface接口:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "Token")]
    int DoSomething(Stream stream);
}

这里是MyClass:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CallbackRequestService : ICallbackRequestService
{
    public int DoSomething(Stream stream)
    {
        StreamReader ms = new StreamReader(stream);
        string data = ms.ReadToEnd().Trim();

        // This throws correctly a 403 Forbidden
        // throw new WebFaultException<string>("Test", HttpStatusCode.Forbidden)

        ms.close();

        // This throws a 400 Bad Request instead of 403 Forbidden,
        // because the stream was closed before this
        // throw new WebFaultException<string>("Test", HttpStatusCode.Forbidden)

        // If no exception at all happens, this correctly returns 9999,
        // regardless if the stream was closed or not
        return 9999;
    }
}

我最初使用在流周围使用以确保它将被正确关闭和处理。然而,在意识到关闭和/或处置将最终达到400之后,如果我抛出任何异常,我真的不知道我是否应该关闭该流。

有谁知道这里有什么问题?

1 个答案:

答案 0 :(得分:1)

代码本身并没有错,但成功取决于流的来源。

您尝试关闭的流是帖子请求的正文。对于这些类型的操作,您可能希望使用流的副本:

var ms= new MemoryStream();
stream.CopyTo(ms);
memstream.Position = 0;
using (var reader = new StreamReader(ms))
{
    string data = ms.ReadToEnd().Trim();
}

源流本身应该保持不变。换句话说,您不应该关闭流。该应用程序会为您处理。