Setting header causes: Collection was modified; enumeration operation may not execute. (WP6)

Topics: Web Api
Feb 3, 2012 at 1:04 PM
Edited Feb 3, 2012 at 1:17 PM

I am trying to set an ETag based on this blog article

Attempt 1: Using a DelegatingHandler

However I am having issues because Wp6 read operations are deliberately asynchronous which means I cannot retrieve the original object to determine the version in a synchronous way.

My asynchronous approach is below:

          ObjectContent oc = response.Content as ObjectContent;
          if (oc != null)
                  t =>
                          // TODO: Setting this sometimes causes a "Collection was modified; enumeration operation may not execute."
                          //       because the CopyHeadersToNameValueCollection is executing at the same time
                          response.Headers.ETag = ETagProvider.GetETag(t.Result);                        

This doesn't work because it spawns the asynchronous Read which eventually completes and tries to update the Headers collection, meanwhile the parent task in my DelegatingHandler thinks it's finished so the HttpMessageHandlerChannel goes into the ContinueReplyPath which eventually calls into CopyHeadersToNameValueCollection. This means two threads trying to access the same collection, hence the error: Collection was modified; enumeration operation may not execute (takes a bit of hammering the F5 key to get this error!)

Attempt 2: Using a MediaTypeFormatter

The alternative approach discussed in the docs below suggest using a MediaTypeFormatter:

However I cannot see any good methods where I have access to the object and the headers collection since OnWriteToStream only exposes the request headers and overriding OnGetResponseHeaders only has the types and raw response message.

Please can anyone help? Should I be trying to read the value synchronously (e.g. accessing the Result property which will suspend the current thread) - seems like making a deliberately async call synchronous is a bad idea that might work locally but fail under load. Should a MediaTypeFormatter work? Is my approach all wrong? :-)

Feb 3, 2012 at 3:20 PM

I don't really know what you mean by saying you can't get the response.

Everything is ASYNC but that doesn't mean it doesn't run synchronously.

It is just an async operation that starts when you fire it, but when you ask for the result, it waits.

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)        {

return Task.Factory.StartNew(() =>


var response = base.SendAsync(request, cancellationToken).Result;



Feb 3, 2012 at 4:28 PM

I don't think I said I couldn't get the response, it's the object the response is wrapping that I am trying to retrieve (the one originally returned in the Service operation). Perhaps I need to paste some more code :-)

So yes as I mentioned, you can get the object but you have to deliberately call "Result" that forces a call that was async by design into a synchronous call by suspending the current thread until the async operation completes. It just didn't sound like a great idea on what was intended to be an async operation - I presume it was made async for a good reason.

Also I haven't looked under the covers but I don't know if this will give me the original object back or rountrip it via the serialize/deserialize which clearly wouldn't be  efficient. If this were the case it may be better not to set the ETag here at all and instead set it directly in the service where I have access to the object I am returning as per:

But fair enough - in summary your advice is use .Result.

Feb 3, 2012 at 5:07 PM

I don't know if it's bad practice or not to do that. I would assume based on how it was put together, that it was expected by the architects that you would sometimes make your own task, and invoke .Result off the base.Async method.

I can't give really any good feedback on whether it is "proper" or not, only they can :(

Also I am pretty sure I read somewhere that if you read the content multiple times, it will only serialize once.
It was one of the pitfalls of using WCF because it would serialize it over and over and over again.

Feb 6, 2012 at 8:30 AM

Cool thanks for the response. Indeed tracing the code through, calling .Result doesn't appear to do anything too crazy other than use a task to asynchronously get a protected property value and then waits for the completion of that. It didn't cause any deserialization to kick in because as you said the value is cached within the ObjectContent