如果流被处理,带有 Stream 参数的 WCF REST 服务将抛出 400
WCF REST Service with Stream parameter throws 400 if stream is disposed
我有一个行为非常尴尬的 WCF REST 服务。如果我使用普通参数,例如 int,然后我抛出任何类型的 WebFaultException,我没有任何问题。例如,我可以抛出 403。但是,如果我有一个 Stream 作为参数,我关闭 and/or 处理流并在以后的任何时候抛出 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 来确保它会被正确关闭和处置。然而,在意识到关闭 and/or 处理将以 400 结束后,如果我抛出任何类型的异常,我真的不知道我是否应该关闭流。
有人知道这里出了什么问题吗?
代码本身并没有错,但成功与否取决于流的来源。
您试图关闭的流是 post 请求的主体。对于这些类型的操作,您可能需要使用流的副本:
var ms= new MemoryStream();
stream.CopyTo(ms);
memstream.Position = 0;
using (var reader = new StreamReader(ms))
{
string data = ms.ReadToEnd().Trim();
}
源流本身应该保持独立。换句话说,您不应该关闭流。该应用程序会为您处理。
我有一个行为非常尴尬的 WCF REST 服务。如果我使用普通参数,例如 int,然后我抛出任何类型的 WebFaultException,我没有任何问题。例如,我可以抛出 403。但是,如果我有一个 Stream 作为参数,我关闭 and/or 处理流并在以后的任何时候抛出 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 来确保它会被正确关闭和处置。然而,在意识到关闭 and/or 处理将以 400 结束后,如果我抛出任何类型的异常,我真的不知道我是否应该关闭流。
有人知道这里出了什么问题吗?
代码本身并没有错,但成功与否取决于流的来源。
您试图关闭的流是 post 请求的主体。对于这些类型的操作,您可能需要使用流的副本:
var ms= new MemoryStream();
stream.CopyTo(ms);
memstream.Position = 0;
using (var reader = new StreamReader(ms))
{
string data = ms.ReadToEnd().Trim();
}
源流本身应该保持独立。换句话说,您不应该关闭流。该应用程序会为您处理。