2017-04-24 53 views
0

在下面的代碼片段中,我試圖實現一個DelegatingHandler。你會發現,在SendAsync方法,我從請求傳遞到InnerHandler的常規做法偏離...在DelegatingHandler中使用HttpClient時出錯:請求消息已經發送。無法多次發送相同的請求消息

base.SendAsync(request, cancellationToken); 

...,而是正在創建的HttpClient的新實例,對此我傳遞要求:

new HttpClient().SendAsync(request, cancellationToken); 

這可以在裸骨片段這樣一個看起來很奇怪,但這裏的想法是將請求傳遞到根據某些條件不同HttpClientHandlers,所以我需要能夠實例化動態地使用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

望着HttpClient的源代碼,我現在看到的例外來自:https://github.com/dotnet/corefx/blob/master/src/System.Net.Http/ src/System/Net/Http/HttpClient.cs#L599 看起來像我的代碼導致請求通過兩個HttpClient實例:只要第一個看到它,它會將其標記爲已發送,到達第二個它已經損壞的貨物。儘管如此,仍然需要幫助尋找解決方法 - 簡單地克隆請求看起來像是一個愚蠢的方式來處理這個問題。 –

回答

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

} 
+0

謝謝@andym1978,但是您發佈的響應是調用基類的SendAsync方法的一個示例(這就是爲什麼您需要在構造函數中定義內部處理程序的原因)。正如我在問題中提到的那樣,我需要在SendAsync覆蓋中創建一個新的HttpClient實例的靈活性,在這種情況下,永遠不會調用內部處理程序。再次感謝您的幫助。 –

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

    } 

} 
+0

非線程安全... – Tratcher

相關問題