Web Api请求在将内容复制到流时会出现“错误”。

时间:2016-03-01 13:41:24

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

我正在尝试实施此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);
}

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

可能是因为内容在这里被读取,它不再可用吗?如果是这样,我怎么能在方法中使它?此处的内容是否与HttpRequestMessage相同? This可能包含答案。

4 个答案:

答案 0 :(得分:3)

只是一个猜测,应该发布评论,但我想要包含一个代码片段:

也许您在Post块中调用using函数,但不要使用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();

答案 1 :(得分:2)

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

答案 2 :(得分:1)

我希望这篇(已故)的帖子有一天会帮助某人......

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

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

我发现用 MultipartMemoryStreamProvider 替换 MultipartFormDataStreamProvider 效果很好 - 让您根据需要阅读上传的文件

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

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

答案 3 :(得分:0)

我解决了这个问题,我的问题是响应在 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();