2015-12-03 12 views
6

मैं .NET HttpClient कक्षा (.NET 4.5.1, System.Net.Http v4.0.0.0) के साथ किसी समस्या में भाग रहा हूं। मैं HttpClient.GetAsync पर कॉल कर रहा हूं, CancellationToken में गुजर रहा हूं (एक Nuget पैकेज के हिस्से के रूप में जो वेब सर्विसेज के बीच कॉल को सारणीबद्ध करता है)। यदि कॉल करने से पहले टोकन रद्द कर दिया गया है, तो अनुरोध अपवाद फेंकने के बिना चला जाता है। यह व्यवहार सही प्रतीत नहीं होता है।.NET HttpClient - रद्द रद्द किया गया टोकन अनुरोध रद्द नहीं कर रहा

मेरे परीक्षण (अधूरा, पूरी तरह से नहीं लिखा - कोई अपवाद नहीं जांच):

[TestMethod] 
public async Task Should_Cancel_If_Cancellation_Token_Called() 
{ 
    var endpoint = "nonexistent"; 
    var cancellationTokenSource = new CancellationTokenSource(); 

    var _mockHttpMessageHandler = new MockHttpMessageHandler(); 
    _mockHttpMessageHandler 
     .When("*") 
     .Respond(HttpStatusCode.OK); 

    var _apiClient = new ApiClientService(new HttpClient(_mockHttpMessageHandler)); 
    cancellationTokenSource.Cancel(); 

    var result = await _apiClient.Get<string>(endpoint, null, cancellationTokenSource.Token); 
} 

विधि मैं परीक्षण कर रहा हूँ:

public async Task<T> Get<T>(string endpoint, IEnumerable<KeyValuePair<string, string>> parameters = null, CancellationToken cancellationToken = default(CancellationToken)) 
{ 
    var builder = new UriBuilder(Properties.Settings.Default.MyEndpointHost + endpoint); 
    builder.Query = buildQueryStringFromParameters(parameters); 

    _httpClient.DefaultRequestHeaders.Accept.Clear(); 
    _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

    try 
    { 
     // After this, we really shouldn't continue. 
     var request = await _httpClient.GetAsync(builder.Uri, cancellationToken); 

     if (!request.IsSuccessStatusCode) 
     { 
      if (request.StatusCode >= HttpStatusCode.BadRequest && request.StatusCode < HttpStatusCode.InternalServerError) 
      { 
       throw new EndpointClientException("Service responded with an error message.", request.StatusCode, request.ReasonPhrase); 
      } 

      if (request.StatusCode >= HttpStatusCode.InternalServerError && (int)request.StatusCode < 600) 
      { 
       throw new EndpointServerException("An error occurred in the Service endpoint.", request.StatusCode, request.ReasonPhrase); 
      } 
     } 

     var json = await request.Content.ReadAsStringAsync(); 
     return JsonConvert.DeserializeObject<T>(json); 
    } 
    catch (Exception ex) 
    { 
     throw; 
    } 
} 

मुझे पता है कि मैं रद्द करने की स्थिति देख सकते हैं HttpClient.GetAsync पर कॉल करने से पहले टोकन और रद्दीकरण का अनुरोध किया गया है तो फेंक दें। मुझे पता है कि मैं HttpClient अनुरोध को रद्द करने के लिए एक प्रतिनिधि भी पंजीकृत कर सकता हूं। हालांकि, ऐसा लगता है कि HttpClient विधि को टोकन पास करने के लिए मुझे इसके लिए ख्याल रखना चाहिए (या, अन्य बात, क्या बात है?) तो मुझे आश्चर्य है कि मुझे कुछ याद आ रहा है या नहीं। मेरे पास HttpClient स्रोत कोड तक पहुंच नहीं है।

क्यों HttpClient.GetAsync मेरा रद्दीकरण टोकन नहीं देख रहा है और जब मैं इसे पास करता हूं तो इसकी प्रक्रिया को निरस्त कर रहा हूं?

+0

आप कौन से HTTP त्रुटि कोड को अपने रद्दीकरण टोकन को वापस करने की उम्मीद करते हैं? –

उत्तर

2

HttpClient रद्दीकरण टोकन स्वयं की जांच नहीं करता है, यह इसे संदेश हैंडलर पर भेजता है जब यह SendAsync विधि कहता है। इसके बाद यह SendAsync से लौटे गए कार्य पर निरंतरता के लिए पंजीकृत होता है और संदेश हैंडलर से वापस लौटाया गया कार्य रद्द कर दिया गया था, तो अपना कार्य रद्द कर दिया जाएगा।

तो आपके परिदृश्य में समस्या MockHttpMessageHandler के कार्यान्वयन में है जो प्रतीत होता है कि रद्दीकरण टोकन की जांच नहीं होती है।

ध्यान दें, HttpClient अपने खाली निर्माता के माध्यम से कहा जाता है कि अगर, उसका आंतरिक HttpClientHandler जो रद्द टोकन उस अनुरोध को रोकता है और कार्य को रद्द करता है पर एक प्रतिनिधि पंजीकृत करता है उपयोग करता है।

+0

डी ओह! यह हमेशा कुछ आसान है, है ना। यह वास्तव में समझ में आता है, हालांकि - मुझे पता था कि 'HttpClient' अंतर्निहित हैंडलर के लिए एक रैपर था, लेकिन किसी भी तरह से मैंने रद्दीकरण टोकन में आने पर प्रभावों के बारे में नहीं सोचा था। इस मामले में, मुझे लगता है कि मैं वास्तव में अंतर्निहित कार्यान्वयन का परीक्षण नहीं कर पाऊंगा जब तक कि मैंने वास्तव में एक पूर्ण HTTP अनुरोध नहीं किया (या कम से कम वास्तविक हैंडलर में बुलाया जाता है)। –

+0

आपको एक पूर्ण HTTP अनुरोध करने की आवश्यकता नहीं है। अपने नकली में, 'SendAsync' के ओवरराइड में, आप विधि की शुरुआत में टोकन की जांच कर सकते हैं। – tzachs

+0

मैं मॉकिंग के लिए https://github.com/richardszalay/mockhttp का उपयोग कर रहा हूं। मैं अपने रेपो में एक मुद्दा जोड़ूंगा, लेकिन एहसास हुआ कि वास्तव में नकली के बिना अनुरोध करना आसान हो सकता है क्योंकि रद्दीकरण टोकन को इसे रद्द करना चाहिए। –

संबंधित मुद्दे