【问题标题】:Web Api Request Throws "Error while copying content to a stream."Web Api 请求引发“将内容复制到流时出错”。
【发布时间】:2016-03-01 13:41:24
【问题描述】:

我正在尝试实现这个code example,但得到一个HttpRequestException - “将内容复制到流时出错。”当调用ReadAsStringAsync() 方法时。内部异常是“无法访问已处置的对象。”我正在使用 Fiddler 提出请求。我不明白。有人可以解释为什么我会收到此异常并提供解决方案吗?

Web API 方法:

public async Task<HttpResponseMessage> 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}

编辑:

我有一个线索,但需要验证。在 Web Api 控制器上,我有一个 ActionFilterAttribute,在它的 OnActionExecuting 覆盖中,有这样一行:

public override async void OnActionExecuting(HttpActionContext actionContext)
{
    // omitted code
    actionContext.Request.Content.ReadAsStreamAsync();
}

会不会是因为在此处阅读了内容,所以它不再可用?如果是这样,我怎样才能使它在方法中可用?这里的Content和HttpRequestMessage一样吗? This 可能包含答案。

【问题讨论】:

  • 你是怎么调用这个方法的?
  • @YuvalItzchakov...我正在使用 Fiddler
  • 此方法是 Web API 操作吗?
  • @YuvalItzchakov...是的,它是 Web Api 控制器上的一种方法
  • @YuvalItzchakov...请看我的编辑,谢谢

标签: c# asp.net-web-api


【解决方案1】:

只是一个猜测,应该作为评论发布,但我想包含一个代码 sn-p:

也许您在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: close,在某些情况下您重用主机时可能会导致异常(搜索更多信息)

request.Version = HttpVersion.Version10;
var jsonString = await request.Content.ReadAsStringAsync();

【讨论】:

  • 谢谢,这些都不行
【解决方案2】:

由于控制器的ActionFilterAttribute'sOnActionExecuting方法正在调用ReadAsStreamAsync,无法再次读取内容。我将ReadAsStreamAsync 更改为ReadAsStringAsync,请求的内容在控制器中可用。显然, ReadAsStringAsync 缓冲内容,因此它仍然可用。这个link 提供了答案。

【讨论】:

    【解决方案3】:

    我希望这篇(迟到的)帖子有一天能对某人有所帮助...

    简而言之:接受的答案建议将整个文件作为字符串(而不是流)读取,以绕过读取问题

    但是...将文件作为字符串读取并不是一个好主意

    我发现将 MultipartFormDataStreamProvider 替换为 MultipartMemoryStreamProvider 效果很好 - 让您可以根据需要读取上传的文件

    我的代码(至少是它的相关部分)

        [HttpPost]
        [Route("upload/file")] // you may replace this route to suit your api service
        public async Task<IHttpActionResult> 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);
            }
        }
    

    【讨论】:

    • 谢谢,我遇到了和你一样的问题。这完美解决了!
    【解决方案4】:

    我解决了这个问题,我的问题是响应在 gzip 中:

    var handler = new HttpClientHandler();
            if (handler.SupportsAutomaticDecompression)
            {
                handler.AutomaticDecompression = DecompressionMethods.GZip |
                                                 DecompressionMethods.Deflate;
            }
            client = new HttpClient(handler);
    
    var content = new FormUrlEncodedContent(valoresPost);
    var response = await client.PostAsync(url, content);
            
                    var contenidoPdf = await response.Content.ReadAsByteArrayAsync();
                 
    

    【讨论】:

      【解决方案5】:

      我正在添加对话,因为我在不同的上下文中遇到了这个错误。对我来说,我有一个从我的网络应用程序到一个单独的 API 的现有调用。它以前工作过,然后停止了,我收到了这个错误,无法找到原因。结果是我的实体框架中的循环引用,本质上是两个不应该存在的对象之间的导航属性。它并没有破坏 API,因为我假设 EF 具有导航属性将填充的深度以防止堆栈溢出的默认配置,但它一定已经压倒了接收端的流并导致连接超时。

      【讨论】:

        猜你喜欢
        • 2020-04-10
        • 1970-01-01
        • 1970-01-01
        • 2016-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-24
        • 2018-02-15
        相关资源
        最近更新 更多