如果流被释放,带有 Stream 参数的 WCF REST 服务会抛出 400
Posted
技术标签:
【中文标题】如果流被释放,带有 Stream 参数的 WCF REST 服务会抛出 400【英文标题】:WCF REST Service with Stream parameter throws 400 if stream is disposed 【发布时间】:2018-09-16 01:16:51 【问题描述】:我有一个行为非常尴尬的 WCF REST 服务。如果我使用普通参数,例如 int,然后我抛出任何类型的 WebFaultException,我没有任何问题。例如,我可以抛出 403。但是,如果我有一个 Stream 作为参数,我关闭和/或处置该流并在以后的任何时候抛出一个 WebFaultException,它总是抛出一个 400 Bad Request 而不是其他任何东西。
这是配置:
<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);
这是我的班级:
[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;
我最初在流周围使用了 using 以确保正确关闭和处置它。但是,在意识到关闭和/或处置最终会以 400 结束后,如果我抛出任何类型的异常,我真的不知道我是否应该关闭流。
有人明白这里出了什么问题吗?
【问题讨论】:
【参考方案1】:代码本身没有错,但成功取决于流的来源。
您尝试关闭的流是发布请求的正文。对于这些类型的操作,您可能需要使用流的副本:
var ms= new MemoryStream();
stream.CopyTo(ms);
memstream.Position = 0;
using (var reader = new StreamReader(ms))
string data = ms.ReadToEnd().Trim();
源流本身应该不理会。换句话说,您不应该关闭流。该应用程序会为您处理。
【讨论】:
啊,这就解释了。我希望我是控制流的人,但处理副本解决了问题。以上是关于如果流被释放,带有 Stream 参数的 WCF REST 服务会抛出 400的主要内容,如果未能解决你的问题,请参考以下文章
在 wcf rest 服务 C# 中使用 Stream 作为输入时缺少第一个元素