我似乎无法捕获从System.Net.Http.HttpClient的SendAsync方法抛出的某些异常。具体来说,是从HttpWebRequest.ChechProtocol方法抛出的ProtocolViolationException。代码似乎死锁或挂起,永远不会输入。
我已经创建了一个NUnit单元测试来清楚地说明这个问题。
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);
}
使用StringContent而不是ObjectContent测试通过。我错过了一些简单的东西吗?
更新
基于StringContent允许捕获异常和ObjectContent死锁的事实,我已经能够推断出这与MediaTypeFormatter的WriteToStreamAsync方法有某种关系。
我设法通过将内容“预格式化”到ByteArrayContent来解决这个问题,如下所示:
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;
}
然后像这样消费它:
var content = await CreateContent(
new TestClass(),
"application/json",
new JsonMediaTypeFormatter());
var request = new HttpRequestMessage(HttpMethod.Get, "http://foo.com")
{
Content = content
};
至少可以让捕获物正常工作,但我
答案 0 :(得分:1)
这是HttpClient中的已知错误。您可以通过缓冲自己,设置内容长度(如ByteArrayContent确实)或使用分块传输编码(如果您的平台支持,电话不支持)来解决此问题。