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

34,492

Solution 1

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.

Solution 2

Maybe my two cents will help someone.

I ran into this issue when refreshing the page when debugging the application.

I was using a singleton, but each refresh, it was trying to set the base address. So I just wrapped it in a check to see if the base address had already been set.

The issue for me was, it was trying to set the baseAddress, even though it was already set. You can't do this with a httpClient.

if (_httpClient.BaseAddress == null)
{
    _httpClient.BaseAddress = new Uri(baseAddress);
}

Solution 3

The issue is caused by resetting BaseAddress and headers for the same instance of the httpclient.

I tried

if (_httpClient.BaseAddress == null) 

but I am not keen on this.

In my opinion, a better soloution is to use the httpclientFactory. This will terminate and garbage collect the instance of the httpclient after its use.

private readonly IHttpClientFactory _httpClientFactory;
public Foo (IHttpClientFactory httpClientFactory) 
{
_httpClientFactory = httpClientFactory;
}
public  httpresponse Bar ()
{
_httpClient = _httpClientFactory.CreateClient(command.ClientId);

using var response = await _httpclient.PostAsync(uri,content);
return response;
// here as there is no more reference to the _httpclient, the garbage collector will clean 
// up the _httpclient and release that instance. Next time the method is called a new 
// instance of the _httpclient is created
}

Share:
34,492
Ask
Author by

Ask

Updated on June 25, 2021

Comments

  • Ask
    Ask almost 3 years

    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.

  • Garr Godfrey
    Garr Godfrey over 2 years
    That's all good but I'm really stuck on Cookies. They aren't super common on hitting APIs but sometimes needed on scraping. So, I want to control the cookie container and set it to a new one with some requests. This seems impossible if we want to reuse HttpClient
  • George Helyar
    George Helyar over 2 years
    @GarrGodfrey disabling cookies per-request is possible, but having a separate cookie container for a set of requests requires having a separate HttpClient with a separate SocketsHttpHandler, so you won't be able to use a singleton HttpClient in this case anyway. You may be able to pool this with IHttpClientFactory. If you want a more detailed answer then please ask a separate question.
  • Garr Godfrey
    Garr Godfrey over 2 years
    It fails changing value of UseCookies after first use with same error as changing BaseAddress. HttpClient may just be more trouble than it is worth.
  • Möoz
    Möoz over 2 years
    This actually helped me a lot, it was exactly what I was facing.
  • AndrewGentry
    AndrewGentry over 2 years
    Love the use of a factory here. Should note that it requires dependency injection though, which may not fit all use cases.