none
Behavior difference between VS2010 and VS2012 Unit Testing (SerializationException)

    Question

  • We recently moved from VS2010 to VS2012 to leverage the Claims entities in .NET4.5 and loose WIF.

    For legacy reasons, in the ClaimsPrincipal we are adding a custom class inheriting ClaimsIdentity that is not marked as [Serialiazable]. In General the information this Identity class holds are not Serializable.

    The code flow passes through a code like this

    XmlSchema _xmlSchema = XmlSchema.Read(reader, new ValidationEventHandler(SchemaValidationCallback));
    
    1. Before this line of code executes, the Current Thread Principal has been initialized with a ClaimsPrincipal like described previously.

    When the above command executes a SerializationException is through by the .NET pipeline with the following stack trace.

       at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
       at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
       at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
       at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
       at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
       at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
       at System.Security.Claims.ClaimsPrincipal.SerializeIdentities()
       at System.Security.Claims.ClaimsPrincipal.OnSerializingMethod(StreamingContext context)
    
       at System.AppDomain.get_Evidence()
       at System.AppDomain.get_EvidenceNoDemand()
       at System.AppDomain.get_Evidence()
       at System.Configuration.ClientConfigPaths.GetEvidenceInfo(AppDomain appDomain, String exePath, String& typeName)
       at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(AppDomain appDomain, String exePath)
       at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
       at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
       at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
       at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
       at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
       at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
       at System.Configuration.ConfigurationManager.GetSection(String sectionName)
       at System.Xml.XmlConfiguration.XmlReaderSection.get_ProhibitDefaultUrlResolver()
       at System.Xml.Schema.Parser..ctor(SchemaType schemaType, XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler)
       at System.Xml.Schema.XmlSchema.Read(XmlReader reader, ValidationEventHandler validationEventHandler)

    It looks like the .net pipeline is trying to initialize some configuration and at some point decides to probably jump between AppDomain and then do the serialization.

    This is weird because the problem is not between different 

    I tried several fixes to circumvent this.

    1. Added an empty app.config on the unit test project but it didn't matter. So FAILED
    2. Tried implementing the serialization interfaces on the custom ClaimsIdentity to get ownership of the process. It FAILED
    3. I created an empty/dummy custom ClaimsPrincipal without marking it as Serializable. It WORKED.

    It looks like the new ClaimsPrincipal does more than its predecessor in WIF. It is marked as Serializable and as consequent tries to serialize all identities.

    I don't like solution No3 although it is relatively transparent to implement. 

    What I would like to know is whether the behavior change is because of Visual studio version change or mainly because of the changes in the ClaimsPrincipal from WIF to .NET4.5. As many other people online, we are dissapointed with the Unit Testing in VS2012. It feels incomplete and there is a lot of ranting online about it, so it could be that this is another change....

    I also would like to know if there is a way to actually control the flow. I can't find any explanation for this happening.


    Thursday, January 24, 2013 10:16 AM

Answers

All replies

  • Hi Sarafian,

    I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay. Appreciate your patience.

    Best regards,


    Amanda Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, January 25, 2013 1:31 AM
  • Hi,

    Any luck?

    As I said I know a solution but I would like a cleaner one or at least an explanation so we understand as a team why we had to do the additional modifications.

    Posted the same in stackoverflow http://stackoverflow.com/questions/14731507/behavior-difference-between-vs2010-and-vs2012-unit-testing-serializationexcepti
    • Edited by a.sarafian Wednesday, February 06, 2013 2:31 PM
    Sunday, January 27, 2013 10:40 PM
  • Please see the following outlining the changes in .NET Framework 4.5

    http://msdn.microsoft.com/en-us/library/system.security.claims.claimsprincipal.aspx

    From a support perspective this is really beyond what we can do here in the forums. If you cannot determine your answer here or on your own, consider opening a support case with us. Visit this link to see the various support options that are available to better meet your needs:  http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

    Thank you

    Friday, February 08, 2013 7:03 PM
  • Hi,

    I really don't think the above should be marked as an answer, as it doesn't resolve the issue, and nor does it help progress it - because directly opening a support case doesn't help anyone else who is experiencing this issue. I am seeing the above issue, tests are running perfectly through Visual Studio 2010 Ultimate, and the exact same tests (compiled against .net framework 4.0) are failing on the serialization error described above when the tests are run via Visual Studio 2012.

    As such, I don't think this problem can be caused directly by .net Framework 4.5 - as I am seeing it when using .net Framework 4.0, and a more likely explanation is what is suggested by the title of this issue, that the issues are caused by a difference in behaviour in mstest between VS2010 and VS2012.

    The following URL has what looks like a more appropriate explanation - that the appdomain behaviour of MS test is different across the versions:
    http://forums.lhotka.net/forums/p/11545/53518.aspx

    Regards,

    Nick


    • Edited by pattmania Thursday, April 25, 2013 4:27 PM
    Thursday, April 25, 2013 7:42 AM
  • I think I've got this problem sorted now.

    With respect to this problem, I think that the key behavioural difference between the 2010 and 2012 test runners is that the 2010 runner causes the ConfigurationManager class to be fully initialized prior to running the test.

    When ConfigurationManager is initialized it reads from AppDomain.Evidence, which causes a stack walk - if you have placed a custom principal on the thread this ends up being de-serialized in the original AppDomain, which fails with the SerializationException you're seeing.

    The fix is a little dirty, but if you make a call to ConfigurationManager.GetSection("ANY DUMMY TEXT") prior to your test then things should start working again.

    FWIW, we have a base class that all our unit test classes derive from - putting this call in the constructor of that base class works fine.

    HTH,

    Mike

    • Proposed as answer by Mike Goatly Wednesday, May 01, 2013 12:25 PM
    Wednesday, May 01, 2013 12:25 PM