'Exception when using SDK (HttpHeaders Collection was modified; enumeration operation may not execute.)
I'm having an issue with some code that I'm integration testing. I've searched other posts for issues relating to this exception, but in most of them it seems they're doing some manual editing of a collection when they shouldn't be.
I am working with an SDK written by someone else that encapsulates HttpClient. When instiantiating and setting up the SDK's client, I have to set the api key. The SDK provides a method for this on the client class. It looks like
public async Task SetApiKey(string apiKey)
{
await Task.Run(() =>
{
_apiKey = apiKey;
SetHeaders();
}).ConfigureAwait(false);
}
private void SetHeaders()
{
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Add("X-Api-Key", _apiKey);
_client.DefaultRequestHeaders.Add("X-Use-Raw", _useRawMode.ToString().ToLower());
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
I use this in my test and then attempt to use the client to retrieve something from the web api. This is an example of how it would be set up (_options contains the base url, etc).
var sdkClient = new SdkClient(_options);
await sdkClient.SetApiKey(apiKey);
var domainObject = await sdkClient.GetById(id);
GetById would contain some code like this. It would also map/serialize to the domain model, handle errors, etc.
var response = await _client.GetAsync(${BaseUrl}{Id}").ConfigureAwait(false);
Often, but not always, this throws an exception
Message:
System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
Stack Trace:
Enumerator.MoveNext()
HttpHeaders.AddHeaders(HttpHeaders sourceHeaders)
HttpRequestHeaders.AddHeaders(HttpHeaders sourceHeaders)
HttpClient.PrepareRequestMessage(HttpRequestMessage request)
HttpClient.CheckRequestBeforeSend(HttpRequestMessage request)
HttpClient.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
HttpClient.GetAsync(String requestUri)
Since it's not happening every time, I initially thought that a race condition was happening within the SDK, trying to set the headers while the request is being sent. However, I looked at the SDK code (that I've shared above) and am under the impression that "await Task.Run" should wait for the work in the background thread to be finished before the task is completed and SetApiKey returns. Then the client should be able to make the request no problem?
If there's something I'm lacking in my understanding of async await/threading, or if there's something else I'm missing - an explanation would be great, thanks.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
