我有一个WCF REST项目,该项目返回http状态代码作为WebFaultExceptions。这对于GET调用非常有效,但是我在获取POST调用返回的WebFaultException时遇到问题。请求正文中的数据使用的内容类型为“ application / x-www-form-urlencoded; charset = utf-8”。我认为问题在于,当上下文切换出using子句以引发WebFaultException时,基础请求流已关闭。
如果在“ using”子句之前抛出WebFaultException,则按预期返回异常。如果我从“ using”子句中抛出WebFaultException,则异常不会返回给客户端。
在使用流读取器读取请求正文时,是否有人对如何成功引发WebFaultException有任何建议?
这是我的服务器端代码的缩写版本。请注意,此示例的httpstatuscodes对于我的实际实现而言并不现实。
[WebInvoke(Method = "POST"
, UriTemplate = "urls/{id}"
, BodyStyle = WebMessageBodyStyle.WrappedRequest
)]
public string PostItem(string id, object streamdata)
{
int _id = 0;
if (int.TryParse(companyIdSr2, out _id))
{
using (System.IO.StreamReader reader = new System.IO.StreamReader(streamdata))
{
string body = reader.ReadToEnd();
if(string.IsNullOrEmpty(body))
{
// this exception doesn't make it back to the client's request object
ThrowError(HttpStatusCode.BadRequest, "empty body");
}
}
}
else
{
// this exception is successfully returned to the client's request object
ThrowError(HttpStatusCode.BadRequest, "invalid id");
}
}
private static void ThrowError(HttpStatusCode status, string message)
{
request_error error = new request_error
{
request_url = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.OriginalString,
error_status_code = status.ToString(),
error_message = message,
};
throw new WebFaultException<request_error>(error, status);
}
public class request_error
{
[XmlElement("request_url")]
public string request_url { get; set; }
[XmlElement("error_status_code")]
public string error_status_code { get; set; }
[XmlElement("error_message")]
public string error_message { get; set; }
}
我已经看到了这个问题-Wrong WebFaultException when using a Stream and closing the stream-尽管它在某种程度上解决了该问题,但仍然有待解决的问题是不丢弃或关闭流是否合理。
非常感谢,
特里
最佳答案
您链接到的question现在已经收到接受的答案,可以解决您的问题。
您声明:
尽管它在某种程度上解决了该问题,但仍然有待解决的问题是不丢弃或关闭流是否合理。
为此,答案指出:
但是最好不要不处理就离开StreamReader,因为它无法清理任何非托管资源。
为了证明这一点,我们在另一个StackOverflow线程上有以下答案,该线程争辩说为什么调用Dispose()
很重要:https://stackoverflow.com/a/2548694/700926
为了解决您在问题中提出的最初问题(WebFaultException
不会发送回客户端),我最终按照this answer中的建议进行操作-将System.IO.StreamReader
子类化并覆盖Close
,这样它告诉StreamReader仅释放非托管资源,而不关闭流。
我的WcfFriendlyStreamReader看起来像这样:
public class WcfFriendlyStreamReader : StreamReader
{
public WcfFriendlyStreamReader(Stream s) : base(s) { }
public override void Close()
{
base.Dispose(false);
}
}
从MSDN documentation调用
Dispose(false)
可以看出,它仅释放非托管资源。并且正如反编译器所揭示的那样,这也会导致Stream
保持打开状态,这似乎可以解决问题:protected override void Dispose(bool disposing)
{
try
{
if (this.LeaveOpen || !disposing || this.stream == null)
return;
this.stream.Close();
}
finally
{
if (!this.LeaveOpen && this.stream != null)
{
this.stream = (Stream) null;
this.encoding = (Encoding) null;
this.decoder = (Decoder) null;
this.byteBuffer = (byte[]) null;
this.charBuffer = (char[]) null;
this.charPos = 0;
this.charLen = 0;
base.Dispose(disposing);
}
}
}
关于c# - 如何在C#WCF REST POST中的StreamReader.ReadToEnd()之后引发WebFaultException?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19986488/