WCF / SVC 在使用 StreamReader 时返回 HTML 错误页面而不是 JSON
Posted
技术标签:
【中文标题】WCF / SVC 在使用 StreamReader 时返回 HTML 错误页面而不是 JSON【英文标题】:WCF / SVC Returns a HTML error page instead of JSON when StreamReader used 【发布时间】:2021-11-02 10:25:53 【问题描述】:如果有人能最终让我摆脱痛苦,那就太好了,这让我发疯了!
我目前正在编写一个简单的 WCF / SVC REST 服务,当抛出异常时,我想返回一个带有 HTTP 状态代码的有意义的 JSON。
这一切似乎都很好。
但是,当我尝试从 POST 请求中读取表单数据 (x-www-form-urlencoded) 时,响应是通用 html 页面而不是 JSON。 这只发生在我使用 StreamReader 读取流时。
Service1.svc.cs
public class Service1 : IService1
public Customer DoWork2(Stream stream)
// ************************************************************
// If this block of code is commented out, the response is JSON.
using (var sr = new StreamReader(stream)) // <-- Using stream reader is what causes it to return HTML error page!
var body = sr.ReadToEnd();
var nvc = HttpUtility.ParseQueryString(body);
// ************************************************************
var errorData = new ErrorData("example error", "stuff");
throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
iService.cs
[WebInvoke(Method = "POST", UriTemplate = "/DoWork2", ResponseFormat = WebMessageFormat.Json)]
Service1.Customer DoWork2(Stream stream);
web.config
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
<system.serviceModel>
<services>
<service name="RestfulServiceExample.Service1" behaviorConfiguration="ServiceBehaviour">
<endpoint address="" contract="RestfulServiceExample.IService1" behaviorConfiguration="webHttp" binding="webHttpBinding" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<!--<behavior>
--><!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --><!--
<serviceMetadata httpGetEnabled="true"/>
--><!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --><!--
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>-->
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />-->
</system.serviceModel>
<!--<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>-->
</configuration>
有谁知道为什么会发生这种情况以及我该如何解决这个问题?
谢谢!
【问题讨论】:
我的猜测是 html 是 YSOD,可能有 500 错误。检查 html 并查看内容。 错误页面的标题为“请求错误”,其中包含消息服务器在处理请求时遇到错误。异常消息是“消息对象已被释放。”。 ...... 异常堆栈跟踪是:在 System.ServiceModel.OperationContext.get_IncomingMessageProperties() 在 System.ServiceModel.Dispatcher.WebErrorHandler.ProvideFault(Exception error, MessageVersion 版本,Message&故障) 经过一番挖掘,我在 *** 上找到了这篇文章;看到这里...***.com/questions/13622537/… 看起来是因为这个...“发生这种情况是因为 StreamReader 接管了流的'所有权'。换句话说,它让自己负责关闭源流。尽快当您的程序调用 Dispose 或 Close(在您的情况下保留 using 语句范围)时,它也会处理源流。在您的情况下调用 sr.Dispose()。因此文件流在之后就死了。" 【参考方案1】:在扯掉我的头发之后,在从其他页面中得到一些提示后,我已经找到了问题的根源。
其中一个是这里的帖子...... Wrong WebFaultException when using a Stream and closing the stream
发生这种情况是因为 StreamReader 接管了 溪流。换句话说,它使自己负责关闭 源流。一旦您的程序调用 Dispose 或 Close(离开 您的情况下的 using 语句范围)然后它将处理 源流也是如此。在您的情况下调用 sr.Dispose() 。所以文件 流之后就死了。
为了解决这个问题,我添加了另一个流变量并将原始流复制到该流中。即
var isolatedStream = new MemoryStream();
stream.CopyTo(isolatedStream);
所以方法现在看起来像这样......
public Customer DoWork2(Stream stream)
var isolatedStream = new MemoryStream();
stream.CopyTo(isolatedStream);
using (var sr = new StreamReader(isolatedStream)) // <-- Using stream reader is what causes it to return HTML error page!
var body = sr.ReadToEnd();
var nvc = HttpUtility.ParseQueryString(body);
// ************************************************************
var errorData = new ErrorData("example error", "stuff");
throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest);
响应现在按最初预期返回 JSON 错误响应。
【讨论】:
以上是关于WCF / SVC 在使用 StreamReader 时返回 HTML 错误页面而不是 JSON的主要内容,如果未能解决你的问题,请参考以下文章
WCF / SVC 在使用 StreamReader 时返回 HTML 错误页面而不是 JSON
从 System32 中的文件夹加载 XML 文件以获取 wcf (.svc) c# 代码