So most of us have probably read that we are supposed to reuse instances of HttpClient
instead of using using
and creating new ones. That means I can just create a single instance of HttpClient
in my program and call GetAsync
using a full uri string per request. This leads me to the BaseAddress
property of HttpClient
. Consider the following code:
HttpClient microsoftClient = new HttpClient() { BaseAddress = new Uri("https://www.microsoft.com/") };
HttpClient stackoverflowClient = new HttpClient() { BaseAddress = new Uri("https://stackoverflow.com/") };
var response = microsoftClient.GetAsync("about").Result;
Console.WriteLine($"I {((response.IsSuccessStatusCode) ? "can" : "cannot")} access microsoft.com/about from the microsoft client");
response = microsoftClient.GetAsync("trademarks").Result;
Console.WriteLine($"I {((response.IsSuccessStatusCode) ? "can" : "cannot")} access microsoft.com/trademarks from the microsoft client");
response = stackoverflowClient.GetAsync("company/about").Result;
Console.WriteLine($"I {((response.IsSuccessStatusCode) ? "can" : "cannot")} access stackoverflow.com/company/about from the stackoverflow client");
response = stackoverflowClient.GetAsync("https://www.microsoft.com/about").Result;
Console.WriteLine($"I {((response.IsSuccessStatusCode) ? "can" : "cannot")} access microsoft.com/about from the stackoverflow client");
microsoftClient.BaseAddress = new Uri("https://stackoverflow.com");
response = microsoftClient.GetAsync("company/about").Result;
Console.WriteLine($"I {((response.IsSuccessStatusCode) ? "can" : "cannot")} access stackoverflow.com/company/about from the microsoft client, after changing the BaseAddress");
Up until the last block this code runs fine, even when using the client with the stackoverflow BaseAddress
to access Microsoft. However this code throws an InvalidOperationException
at the beginning of the last block, when reassigning the BaseAddress
, stating
'This instance has already started one or more requests. Properties can only be modified before sending the first request.'
This leads me to the following questions:
- What is the benefit of using
BaseAddress
at all? I could just always use the full address in myGetAsync
call. Is it just for the convenience/performance of not having to build the the full request string? My guess was that it would only create a singleServicePoint
internally as described in the first paragraph of this blog post (or something similar as the post is quite old). - What happens internally that we can't change a property of
HttpClient
, especiallyBaseAddress
, after sending the first request? This seems quite inconvenient if using this property actually yields benefits.