Web Api请求在将内容复制到流时会出现“错误”。
我正在尝试实现此代码示例 ,但获取HttpRequestException
– “ 将内容复制到流时出错 ”。 调用ReadAsStringAsync()
方法时。 内部exception是“ 无法访问已处置的对象” 。 我正在使用Fiddler提出请求。 我不明白。 有人可以解释为什么我得到这个例外并提供解决方案吗?
Web Api方法:
public async Task Post(HttpRequestMessage request) { try { var jsonString = await request.Content.ReadAsStringAsync(); } catch (Exception ex) { throw; } return new HttpResponseMessage(HttpStatusCode.Created); }
提琴手(POST):
User-Agent: Fiddler Host: localhost:23567 Content-Length: 18 Content-Type: application/json; charset=utf-8 Body{"Test":1}
编辑:
我有一个线索,但需要validation。 在Web Api控制器上,我有一个ActionFilterAttribute
,在其OnActionExecuting
覆盖中,有这一行:
public override async void OnActionExecuting(HttpActionContext actionContext) { // omitted code actionContext.Request.Content.ReadAsStreamAsync(); }
可能是因为内容在这里被读取,它不再可用吗? 如果是这样,我怎样才能在方法中使用它? 此处的内容是否与HttpRequestMessage相同? 这可能包含答案。
只是一个猜测,应该发布评论,但我想包括一个代码片段:
也许您在using
块中调用Post
函数,但不要使用await
。
using (HttpRequestMessage request = ...) { // Maybe you use this: Post(request); // Instead of this var response = await Post(request); }
或者您没有正确处理旧连接。
另外,尝试将HttpVersion.Version10
添加到您的请求中,该请求Connection: keep-alive
请求从Connection: keep-alive
更改为Connection: close
,这可能会导致exception,在某些情况下您重用主机(搜索更多信息)
request.Version = HttpVersion.Version10; var jsonString = await request.Content.ReadAsStringAsync();
由于控制器的ActionFilterAttribute's
OnActionExecuting
方法正在调用ReadAsStreamAsync
,因此无法再次读取内容。 我将ReadAsStreamAsync
更改为ReadAsStringAsync
,并且请求的内容在控制器中可用。 显然,ReadAsStringAsync缓冲内容,因此它仍然可用。 这个链接提供了答案。
我希望这篇(已故)的post有一天会帮助某人……
简而言之:接受的答案建议将整个文件读取为字符串(而不是流)以绕过读取问题
但是……将文件作为字符串读取并不是一个好主意
我发现用MultipartMemoryStreamProvider替换MultipartFormDataStreamProvider效果很好 – 让你按需读取你上传的文件
我的代码(至少相关部分)
[HttpPost] [Route("upload/file")] // you may replace this route to suit your api service public async Task Upload() { if (!Request.Content.IsMimeMultipartContent("form-data")) { return BadRequest("Unsupported media type"); } try { var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); if (provider.Contents.Count == 0) return InternalServerError(new Exception("Upload failed")); var file = provider.Contents[0]; // if you handle more then 1 file you can loop provider.Contents var buffer = await file.ReadAsByteArrayAsync(); // .. do whatever needed here return Ok(); } catch (Exception ex) { return BadRequest(ex.GetBaseException().Message); } }