Si è verificato un problema con la classe .NET HttpClient
(.NET 4.5.1, System.Net.Http v4.0.0.0). Sto chiamando HttpClient.GetAsync
, passando in un CancellationToken
(come parte di un pacchetto Nuget che astrae le chiamate tra i servizi web). Se il token è stato cancellato prima che venga effettuata la chiamata, la richiesta passa senza generare un'eccezione. Questo comportamento non sembra corretto..NET HttpClient - Cancellazione annullataToken non annulla richiesta
Il mio test (incompleta, non pienamente scritta - nessun controllo eccezione):
[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);
}
Il metodo che sto testando:
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;
}
}
So che posso controllare lo stato della cancellazione token prima di chiamare HttpClient.GetAsync
e lanciare se la cancellazione è stata richiesta. So che posso anche registrare un delegato per annullare la richiesta HttpClient. Tuttavia, sembra che passare il token al metodo HttpClient dovrebbe occuparsi di questo per me (o, altrimenti, qual è il punto?), Quindi mi chiedo se mi manca qualcosa. Non ho accesso al codice sorgente HttpClient
.
Perché HttpClient.GetAsync
non controlla il mio token di annullamento e interrompe il processo quando lo passo?
Quali codici di errore HTTP si aspettano che ReturnToken restituisca? –