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); } }