WCF/SVC使用StreamReader读取请求流时异常返回HTML而非JSON问题
问题原因
- 你使用
using块包裹StreamReader时,StreamReader释放会默认关闭传入的WCF请求基础流,WCF后续处理WebFaultException、序列化自定义JSON错误响应时,依赖的请求上下文流已经被提前释放,导致WCF自定义错误处理逻辑执行失败。 - 自定义错误逻辑失败后,请求会落到ASP.NET/IIS的默认错误处理流程,最终返回系统默认的HTML错误页。
- 额外触发因素:读完请求流后没有重置流指针位置,也会导致WCF后续读取流内容失败,进一步触发默认错误处理。
可行解决方案
方案1:使用带leaveOpen参数的StreamReader构造函数(推荐)
.NET Framework 4.5及以上版本支持该重载,设置leaveOpen = true后,StreamReader释放时不会关闭基础请求流,同时保证StreamReader自身非托管资源正常释放:
public Customer DoWork2(Stream stream) { using (var sr = new StreamReader(stream, Encoding.UTF8, true, 1024, leaveOpen: true)) { var body = sr.ReadToEnd(); var nvc = HttpUtility.ParseQueryString(body); } // 重置流指针到起始位置,兼容WCF后续可能的流读取操作 if (stream.CanSeek) { stream.Position = 0; } var errorData = new ErrorData("example error", "stuff"); throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest); }
方案2:不使用using块包裹StreamReader
WCF会自行管理请求流的生命周期,不需要开发人员手动释放,直接创建StreamReader读取即可:
public Customer DoWork2(Stream stream) { var sr = new StreamReader(stream); var body = sr.ReadToEnd(); var nvc = HttpUtility.ParseQueryString(body); if (stream.CanSeek) { stream.Position = 0; } var errorData = new ErrorData("example error", "stuff"); throw new WebFaultException<ErrorData>(errorData, HttpStatusCode.BadRequest); }
方案3:配置IIS错误响应透传
如果上述代码修改后仍然出现HTML错误页,说明IIS拦截了400等错误状态码的响应,修改web.config添加如下配置,保留WCF返回的原始响应内容:
<configuration> <system.webServer> <httpErrors errorMode="Detailed" existingResponse="PassThrough" /> </system.webServer> </configuration>
内容的提问来源于stack exchange,提问作者Dom
相关产品推荐
相关产品推荐

