Home Dashboard Directory Help
Search

ExecutionEngineException thrown from DataContractSerializer with IList<T> by jbfranzen


Status: 

Closed
 as Fixed Help for as Fixed


11
0
Sign in
to vote
Type: Bug
ID: 391260
Opened: 1/6/2009 8:18:35 PM
Access Restriction: Public
0
Workaround(s)
view
7
User(s) can reproduce this bug

Description

The DataContractSerializer appears to fail to serialize under the following minimal conditions:

You have two classes, A and B, marked as DataContracts.
Class A has a property which is an IList<B>.

Serialization works fine the first time, but when you deserialize the object, the DataContractSerializer makes the underlying collection a B[] instead of a List<B>. Because of this, when you try to serialize this object again, an ExecutionEngineException is thrown. This seems like a bug -- I should be able to freely round trip serialize and deserialize as many times as I want, but this conversion to an Array causes it to blow up on reserialization. I'm assuming that the fact that an ExecutionEngineException is being thrown has something to do with the IL generated for serialization.

I ran into this problem because we are using WCF with a shared contract. We can't easily change the contract from IList<T> to List<T> (which is a workaround for the problem) because of the way our application is built.

Also, from a usability standpoint, if the property is an IList, it seems like the DataContractSerializer should deserialize it as a List<T> instead of an Array, because although Array implements IList explicitly, many of its operations throw NotSupportExceptions (of course this would be a breaking change now.)
Details
Sign in to post a comment.
Posted by Kostas Karampelas on 3/24/2010 at 5:46 AM
Searching again for a solution on this I encountered the following (open) issue :

https://connect.microsoft.com/wcf/feedback/details/433569/wcf-throws-an-executionengineexception-when-returning-an-array-as-ilist-t?wa=wsignin1.0

In the comments of that issue I found that the hotfix for the KB971030 (http://support.microsoft.com/kb/971030) could resolve the problem, so I tried it. Guess what, it did solve this issue as well!

So, if anyone still has this problem he could try the HotFix (http://code.msdn.microsoft.com/KB971030). Worked for me!

Posted by Kostas Karampelas on 3/2/2010 at 1:33 AM
I can also verify that the problem still exists with .NET 3.5, SP1. It only becomes aparent after deserializing and serializing again the objects. Are there any news on this?
Posted by JoeT12 on 11/19/2009 at 10:21 PM
I can also reproduce this problem. I have a shared code-base for WPF and Silverlight calling RESTful services using DataContractSerializer. After Deserialization, the subsequent serialization causes the ExecutionEngineException under Silverlight (3) only. The WPF client is fine. I am sharing exactly the same code-base.

Thank-you,

Joseph Tillig
Posted by nigor on 10/14/2009 at 10:25 AM
I have SL 3 and .NET 3.5 SP1 and the issue still exists. This ticket is marked as Closed (fixed). Does this mean the fix will appear in the next version of SL?
Posted by nonnb on 10/9/2009 at 6:43 AM
Have also received this issue and appears repeatable (.NET 3.5SP1)
=> Create 2 Entities, a parent with a [DataMember ]property IList<Child>, built into an entity assembly
=> Create the first WCF Service (separate assembly), hosted under IIS7, which instantiates an entity tree (Parent + Children) from the first service and return the entity tree [i.e. [OperationContract]Parent GetParent()]
=> Create a second WCF Service (separate assembly), also hosted IIS7. This service should reference the first service and return return the same Entity graph (i.e. it calls Service1.GetParent and returns this same Parent)
=> Now add a 3rd Project (e.g. Web Forms app) which references the second WCF Service Reference and calls GetParent.
In my case,
Client => Service 2 => Service 1
             Service 2 <=
WORKS (i.e. the Tree is serialized / deserialized successfully the first time)
but when returning the second deserialized / serialized data to the Client, this crashes with ExecutionEngineException. Browser hangs, and VS2008 crashes.

This issue is worked around by wrapping the child as List<T> (IList<T> crashes)
Posted by Jon Miller on 7/7/2009 at 4:22 PM
I'm confused how an IList<T> can be assigned an array to begin with? How is a fixed size array going to support IList<T>.Add()? Alright... I see that it can throw a NotSupportedException. Pretty non-intuitive. Any word on whether the fix for this will indeed be included in .NET 4?
Posted by Jon Miller on 7/7/2009 at 4:10 PM
I think I'm running into the same issue. I really hate WCFs error handling (On a side note, does anyone know if there is a way to turn on WCF trace logging that might shed light into the issue?). I've seen it where it simply closes the HTTP connection and doesn't throw an exception, at least not to the client. Or you get the ExecutionEngineException with a virtually non-existent stack trace. The pathetic thing is how it actually kills the ASP.NET Development Server. Thanks for taking the time to submit this bug. I really hope this gets fixed in .NET 4.0. I've ran into really ugly issues like this that went unfixed. It is quite frustrating when one spends a lot of time debugging issues like this and submitting error reports only to not have the problem get fixed by Microsoft.
Posted by Microsoft on 2/4/2009 at 6:33 PM
I was able to repro this with an IIS hosted service. This is indeed a bug and I traced it back to a known issue which will be fixed in a future release.

Thanks for reporting the issue!
Posted by Microsoft on 2/4/2009 at 11:22 AM
I used a console app. I will try again in ASP .Net and get back to you.

Thanks,
-Asad
Posted by jbfranzen on 2/2/2009 at 6:48 PM
What do you mean you couldn't get the solution "to work"? Which solution? Aspnet.zip or aspnet_simple.zip or both? What do you mean by "self hosted service"? Is it a console app, Windows Forms, Windows Service? As I stated in my post on 1/15: "So far I've determined that the code works fine in console and Windows Forms applications but throws the ExecutionEngineException on the last line in Visual Studio unit tests and ASP.NET applications." So changing the context in which you're running this code *DOES* matter even though I agree with you when you said it shouldn't make a difference. I've reproduced the issue on three systems (two XP and one Vista, all .NET 3.5 SP1) and found references to the issue online:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/d8dfe66f-81a3-4db9-9c35-423f641b1a70/

http://blogs.infosupport.com/blogs/jonathan/archive/2007/08/15/Possible-WCF-Serialization-Issue_3F00_.aspx

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=357192

http://monstersgotmy.net/post/Doppelganger-Datacontract-WCF-Gotcha.aspx

So please, try the code in an ASP.NET web application project like I've done in aspnet_simple.zip if you haven't already.
Posted by Microsoft on 2/2/2009 at 12:06 PM
I am unable to reproduce the problem. I couldn't get your solution to work as is. But I copy pasted the service and client code in a new project and it worked fine (tried using a self hosted service which shouldn't make a difference). I ran this on .Net 3.5 SP1.

Thanks,
-Asad
Posted by jbfranzen on 2/1/2009 at 12:45 AM
This has nothing to do with cross-platform compatibility, because this has nothing to do with how the types are represented in their serialized form. The DataContractSerializer has no problem serializing or deserializing List<T>, DataSets, and plenty of other .NET specific types (including ones marked Serializable), because it can represent them in XML in a cross-platform compatible way. T[], IList<T>, and List<T> all have equivalent collection data contracts and are all equally cross-platform compatible as far as the DCS is concerned. If I were using List<T> on my contract instead of IList<T>, I'd never see an array, yet it would still work fine across platforms.

The question is why the DataContractSerializer uses an array when it sees an IList<T> on the data contract when *deserializing* (I'm not using service reference which by default would have replaced IList<T> with T[]; I'm using a shared interface.) They could just as easily have used a List<T>, or better yet, let us choose how we want to represent it.

From MSDN:
"During deserialization, when the declared type is an interface, the serialization engine chooses a type that implements the declared interface, and the type is instantiated. The known types mechanism (described in Data Contract Known Types) has no effect here; the choice of type is built into WCF."
Posted by Peter Buelens on 1/29/2009 at 2:59 AM
By default, WCF uses DCS (DataContractSerializer), which, for (de)serialization, only uses types that are compatible across platforms.
So when you are using ILIst<T>, the serialization process will use T[] because the latter is cross-platform compatible whereas the former is specific for .NET (System.Collection.Generic.IList<T>).
You will notice that although T[] (from System.Array) and IList<T> are unrelated, they are nevertheless type-compatible. To do this, the .NET runtime needs to perform some ugly things, using hidden classes like SZArrayHelper. It would seem that these ugly details cause the ExecutionEngineException you are seeing. Granted, error handling could be better. Sadly, the probability that it will be corrected before .NET 4.0 is next to zero. The bug exists up to and including 3.5SP1 GDR.
To work around it, you can replace the DataContractSerializer with the NetDataContractSerializer as behavior on all your operation description, both on the client and on the server. This will render your service uninteroperable with non-.NET platforms, but types will be serialized as their actual .NET types and the error will disappear (even if you pass T[]'s as IList<T>'s).

Vincent
Posted by jbfranzen on 1/15/2009 at 8:25 PM
That's odd. I still see it in the attachments (test580160aspnet.zip). Anyway I've attached it again as aspnet.zip. This demonstrates the problem with a console application that calls a WCF service running in ASP.NET. I've also attached aspnet_simple.zip which demonstrates the problem with just an ASP.NET application with one page that uses the DataContractSerializer in Page_Load. That solution represents the simplest way I could reproduce the problem in ASP.NET. So far I've determined that the code works fine in console and Windows Forms applications but throws the ExecutionEngineException on the last line in Visual Studio unit tests and ASP.NET applications.
Posted by Microsoft on 1/15/2009 at 4:42 PM
Thankyou for creating a standalone project for reproducing the problem.I don't see the ASP .Net solution in the attachments. Can you post it again?

Thanks,
-Asad
Posted by jbfranzen on 1/10/2009 at 9:01 AM
I've now reproduced the issue outside of the unit test by using a separate ASP.NET application, which mirrors the conditions under which we originally discovered this problem. I'm attaching the solution. I've also included the workaround (commented out) that we're currently using, which is to replace the array with a List<Bar> in an OnSerializing method. One thing I noticed however is that if I had already run it without the workaround once, causing the failure, I couldn't simply uncomment the line and rebuild for it to work. I had to restart Visual Studio and reopen the solution -- must have something to do with the catastrophic ExecutionEngineException.
Posted by Microsoft on 1/9/2009 at 1:01 AM
Thanks for your response. We are escalating this bug to the product unit who works on that specific feature area. The team will review this issue and make a decision on whether they will fix it or not for the next release.

Thank you,
Visual Studio Product Team
Posted by jbfranzen on 1/8/2009 at 7:00 AM
The problem is more subtle than I thought. I took your solution and it ran fine. When I originally reproduced the issue I did so in a unit test, so I've added a Visual Studio unit test project to your solution and simply called back into the original code from there and I get the issue when I run the unit test. We also have this issue outside the context of unit tests when we're using a client and server with WCF, so I'm not sure what other factor is causing this. I'll attach the new solution.
Posted by Microsoft on 1/7/2009 at 10:35 PM
test580160.zip
Posted by Microsoft on 1/7/2009 at 10:35 PM
Thanks for reporting the issue.
In order to fix the issue, we must first reproduce the issue in our labs. We are unable to reproduce the issue with the steps you provided. See attached test580160.zip.
It may help if you provide us with:
1. a demo project can be used to reproduce this issue.
2. more snapshots.

If we do not receive a response from you after 7-days , we will automatically close your issue. There is no obligation to respond -- at any time you may edit your issue via Connect and change the status to “Active.”

Thank you,
Kylin.Ming
Sign in to post a workaround.