Httpclient This instance has already started one or more requests. Properties can only be modified before sending the first request

Ask picture Ask · Jul 23, 2018 · Viewed 18.7k times · Source

I am creating an application in .Net Core 2.1 and I am using http client for web requests. The issue is I have to send parallel calls to save time and for that I am using Task.WhenAll() method but when I hit this method I get the error "This instance has already started one or more requests. Properties can only be modified before sending the first request" Previously I was using RestSharp and everything was fine but I want to use httpclient. Here is the code:

public async Task<User> AddUser(string email)
{
    var url = "user/";
    _client.BaseAddress = new Uri("https://myWeb.com/");
    _client.DefaultRequestHeaders.Accept.Clear();
    _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants."application/json"));
    _client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    var json = new {email = email }
    var response = await _client.PostAsJsonAsync(url,json);
    if (response .IsSuccessStatusCode)
    { ....

Here is the constructor:

private readonly HttpClient _httpClient;

public UserRepository(HttpClient httpClient)
{         
    _httpClient = httpClient;
}

Method calling:

var user1 = AddUser("[email protected]");
var user2 = AddUser("[email protected]");

await Task.WhenAll(user1, user2);

and here is the startup configuation:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

So what am I doing wrong? Do I need to change AddSingleton with AddTransient() or is there any other issue. One more question do I need to use _client.Dispose() after the response because the tutorial which I followed didn't use dispose method so I am little confused in that.

Answer

George Helyar picture George Helyar · Jul 23, 2018

HttpClient.DefaultRequestHeaders (and BaseAddress) should only be set once, before you make any requests. HttpClient is only safe to use as a singleton if you don't modify it once it's in use.

Rather than setting DefaultRequestHeaders, set the headers on each HttpRequestMessage you are sending.

var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent("{...}", Encoding.UTF8, "application/json");
var response = await _client.SendAsync(request, CancellationToken.None);

Replace "{...}" with your JSON.