在下面的代码片段中,我尝试实现DelegatingHandler。您会注意到,在SendAsync方法中,我偏离了将请求传递给InnerHandler的传统做法......
base.SendAsync(request, cancellationToken);
...而是创建一个HttpClient的新实例,我传递了请求:
new HttpClient().SendAsync(request, cancellationToken);
这在像这样的裸骨片段中可能看起来很奇怪,但这里的想法是根据特定条件将请求传递给不同的HttpClientHandler,因此我需要能够动态地实例化HttpClient。
但是,当我运行此代码时,我收到以下异常:
The request message was already sent. Cannot send the same request message multiple times.
有人可以帮助我理解导致它的原因以及实现我的要求的更好方法(在处理程序中克隆请求而不是传递它,哪个有效,但看起来不优雅)?
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace DelegatingHandlerTest
{
internal static class Program
{
private static void Main()
{
var httpClient = new HttpClient(new MyTestHandler());
var response = httpClient.GetAsync("http://icanhazip.com/").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
private class MyTestHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await new HttpClient().SendAsync(request, cancellationToken);
}
}
}
答案 0 :(得分:0)
DelagatingHandler需要一个内部处理程序来运行,所以看起来你只需要确保在那里传递一个请求处理程序实例。
private static void Main()
{
var httpClient = new HttpClient(new MyTestHandler(new HttpClientHandler()));
var response = httpClient.GetAsync("http://icanhazip.com/").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
private class MyTestHandler : DelegatingHandler
{
public MyTestHandler( HttpClientHandler handler) {
base.InnerHandler = handler;
}
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await base.SendAsync(request, cancellationToken);
}
}
答案 1 :(得分:0)
我可能会误解你的要求,但是如果你只需要在各种处理程序之间做出决定,你是否可以在调用base.SendAsync()之前将相应的HttpClientHandler分配给InnerHandler?像这样:
private class MyTestHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (someCondition)
{
base.InnerHandler = new MyHttpClientHandler(...);
}
else
{
base.InnerHandler = new MyOtherHttpClientHandler(...);
}
return await base.SendAsync(request, cancellationToken);
}
}