为什么我不能用ObjectContent时从HttpClient的SendAsync赶上例外 [英] Why can't I catch exception from HttpClient SendAsync when using ObjectContent

查看:748
本文介绍了为什么我不能用ObjectContent时从HttpClient的SendAsync赶上例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法赶上从System.Net.Http.HttpClient的SendAsync方法抛出某些例外。具体来说,ProtocolViolationException,从HttpWebRequest.ChechProtocol方法抛出。该代码似乎死锁或挂起,并且从未进入渔获物。



我创建了一个NUnit的单元测试来说明这个问题清楚了。

 公共类识别TestClass 
{
公共BOOL TestProperty {搞定;组; }
}

[测试]
公共异步任务CanCatchExceptionFromHttpClientSendAsync()
{
VAR caughtException = FALSE;


{
变种要求=新HttpRequestMessage(HttpMethod.Gethttp://somedomain.com)
{
含量=新ObjectContent<&的TestClass GT;(
新识别TestClass {TestProperty =真}
新JsonMediaTypeFormatter())
};

等待新的HttpClient()SendAsync(要求)。
}
赶上(例外)
{
caughtException = TRUE;
}

Assert.IsTrue(caughtException);
}



使用的StringContent代替ObjectContent测试通过。我失去了一些东西简单?



更新



根据事实的StringContent允许异常被抓住,ObjectContent死锁,我已经能够推断出,这是某种程度上关系到MediaTypeFormatter的WriteToStreamAsync方法。



我已经成功地工作各地通过预先格式化的内容到ByteArrayContent像这样的问题:

 私有静态异步任务< HttpContent> createContent中< T>(
吨价,
串mediaType的,
MediaTypeFormatter格式)
{
变种类型= typeof运算(T);
变种头=新MediaTypeHeaderValue(mediaType的);

HttpContent内容;
使用(VAR流=新的MemoryStream())
{
等待formatter.WriteToStreamAsync(类型,值,流,NULL,NULL);

含量=新ByteArrayContent(stream.ToArray());
}

formatter.SetDefaultContentHeaders(类型,content.Headers,报头);

回报率的内容;
}

和再消费它是这样的:

  VAR内容=等待createContent中(
新识别TestClass(),
应用/ JSON,
新JsonMediaTypeFormatter());

变种要求=新HttpRequestMessage(HttpMethod.Gethttp://foo.com)
{
含量=内容
};

这至少可以让渔获正常工作,但我


< DIV CLASS =h2_lin>解决方案

这是HttpClient的一个已知的bug。您可以通过缓冲自己变通办法,设置内容长度(如ByteArrayContent一样),或者使用块传输编码(如果支持您的平台,不支持电话)。


I can't seem to catch certain exceptions thrown from the System.Net.Http.HttpClient's SendAsync method. Specifically, the ProtocolViolationException, thrown from the HttpWebRequest.ChechProtocol method. The code seems to deadlock or hang, and the catch is never entered.

I've created an NUnit unit test to illustrate the issue clearly.

public class TestClass
{
    public bool TestProperty { get; set; }
}

[Test]
public async Task CanCatchExceptionFromHttpClientSendAsync()
{
    var caughtException = false;

    try
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "http://somedomain.com")
        {
            Content = new ObjectContent<TestClass>(
                new TestClass { TestProperty = true },
                new JsonMediaTypeFormatter())
        };

        await new HttpClient().SendAsync(request);
    }
    catch (Exception)
    {
        caughtException = true;
    }

    Assert.IsTrue(caughtException);
}

using StringContent instead of ObjectContent the test passes. Am I missing something simple?

Update

Based on the fact that StringContent allows the exception to be caught, and ObjectContent deadlocks, I've been able to deduce that this is somehow related to the MediaTypeFormatter's WriteToStreamAsync method.

I've managed to work around the problem by "pre-formatting" the content in to a ByteArrayContent like so:

private static async Task<HttpContent> CreateContent<T>(
    T value,
    string mediaType, 
    MediaTypeFormatter formatter)
{
    var type = typeof(T);
    var header = new MediaTypeHeaderValue(mediaType);

    HttpContent content;
    using (var stream = new MemoryStream())
    {
        await formatter.WriteToStreamAsync(type, value, stream, null, null);

        content = new ByteArrayContent(stream.ToArray());
    }

    formatter.SetDefaultContentHeaders(type, content.Headers, header);

    return content;
}

and then consuming it like this:

var content = await CreateContent(
    new TestClass(), 
    "application/json", 
    new JsonMediaTypeFormatter());

var request = new HttpRequestMessage(HttpMethod.Get, "http://foo.com")
{
    Content = content
};

That at least allows the catch to work properly, but I

解决方案

This is a known bug in HttpClient. You can workaround it by buffering yourself, setting content-length (as ByteArrayContent does) or using chunked transfer encoding (if supported on your platform, not supported on Phone).

这篇关于为什么我不能用ObjectContent时从HttpClient的SendAsync赶上例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆