This is an anti-recipe for the ExecutionEngineException. By an anti-recipe, I mean I will demonstrate how to get a certain result that you never want to get, with the expectation that it will help you steer clear of it.
ExecutionEngineException messages are a bit scary. They happen at a pretty low level, first of all, and aren’t easy to debug. Second, the exception remarks provided on MSDN are:
“Execution engine errors are fatal errors that should never occur. Such errors occur mainly when the execution engine has been corrupted or data is missing.”
I want to point out one scenario which might provoke your code to throw this exception on the principle that forewarned is forearmed. More importantly, don’t freak out if you run into this – there are some easy workarounds.
When writing a service contract for a WCF web service, you may want to use a IEnumerable<T> as the return type. Generally this is fine. If you try to return an array as the underlying type, however, you will get the ExecutionEngineException in .NET 3.5.
This is simply a bug, so you will need to work around it. You have two choices: either change the signature of your service method or change the underlying type.
If you use the extension method ToList() on your array, everything will work fine.
Alternatively, if you are able to rewrite your service contract, just return the array type rather than trying to use IEnumerable<T>, ICollection<T>, or IList<T>, all of which will cause the same scary exception to be thrown if the underlying type is an array of custom objects (e.g. CustomType[]).
Arrays of simple types (e.g. string[]) do not seem to be a problem.
Arrays of custom objects will generate the exception whether they are the return type on art of the signature of the service method or if they are members of an object returned by the service method.
I said there are two workarounds, but there are actually three. This exception seems to only be thrown when you host your service in IIS or Cassini. If you self-host your service, even using the BasicHttpBinding type, the problem doesn’t show up.
To reiterate, the problem occurs when a web service contract specifies an IEnumerable<T>, ICollection<T> or IList<T> as the return type and the underlying type returned is actually an array of custom objects.
This has been noted as a bug by Microsoft (https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=433569). It also appears to be fixed in .NET 4.0. I have ported my troubled code to VS 2010 Beta 1, and the code works fine.
I don’t think this problem is actually encountered that often for two reasons. First, we typically don’t use raw arrays that often. Instead we use generic Lists or even ArrayLists which, even if they are a bit fatter than simple arrays, are awfully convenient. Second, while it is considered to be a best practice to always return least derived types in methods and properties – in practice this seems to be the exception rather than the rule.
Finally, it doesn’t appear to be a problem with the DataContractSerializer as some have suggested elsewhere. I can serialize my data contracts just fine when I use the DataContractSerializer on its own. The problem only seems to happen for me when I try to expose these contracts through a WCF service. Also, if it were a DataContractSerializer problem, changing to self-hosting shouldn’t help.
I get this issue running WCF inside a Windows service, so IIS / Cassini may not be a factor. I was returning an array as ICollection<T>, .NET 3.5
[OperationContract]
ICollection<Blah> GetStuffOutOfDate(ICollection<Blah> data, bool useLatest);
To fix I changed service contract to return / accept arrays –
[OperationContract]
Blah[] GetStuffOutOfDate(Blah[] data, bool useLatest);