Search Unity

UWP DataContractSerializer fails to load configuration section

Discussion in 'Windows' started by skgoodel, Dec 7, 2017.

  1. skgoodel

    skgoodel

    Joined:
    Oct 17, 2017
    Posts:
    3
    I am trying to serialize a simple class in a UWP app using the following code:

    Code (CSharp):
    1. var serializer = new DataContractSerializer(typeof(Data));
    2. using (var stream = new MemoryStream())
    3. using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
    4. {
    5.     serializer.WriteObject(writer, new Data() { Foo = 42 });
    6. }
    However, no matter what I seem to do with the data I run into this exception at runtime:

    Guessing from reference source it looks like the exception happens as the DataContractSerializer tries to read a section from the ConfigurationManager.

    http://referencesource.microsoft.co...ializerSection.cs,4e6898d0a7262dad,references

    However, in UWP the ConfigurationManager no longer exists. I ran into this problem when compiling both .NET 3.5 and .NET 4.6. Has anyone else run into a similar issue? Has anyone else been able to get the DataContractSerializer to work for UWP?
     
  2. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,674
    We'll need a bug report on this.

    What are you using DataContractSerialization for?
     
  3. skgoodel

    skgoodel

    Joined:
    Oct 17, 2017
    Posts:
    3
    I'm using the DataContractSerializer to serialize some game state and send it over the wire as a binary blob.

    EDIT: I will set up a repro and file a bug.
     
    Last edited: Dec 7, 2017
  4. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,674
  5. Tmahlmann

    Tmahlmann

    Joined:
    Feb 7, 2018
    Posts:
    1
    I ran into the same issue when deploying an Android app using the 4.6 .NET runtime and Unity 2017.3f3. Works ok in the editor on Windows.

    ConfigurationErrorsException: Failed to load configuration section for dataContractSerializer.
    • at System.Runtime.Serialization.Configuration.DataContractSerializerSection.UnsafeGetSection () [0x00026] in <3355504862ba4e7f92c25c91d98a6780>:0
    • at System.Runtime.Serialization.DataContract.get_ConfigSection () [0x00007] in <3355504862ba4e7f92c25c91d98a6780>:0
    • at System.Runtime.Serialization.DataContract.LoadKnownTypesFromConfig (System.Type type, System.Collections.Generic.Dictionary`2[TKey,TValue] typesChecked, System.Collections.Generic.Dictionary`2[System.Xml.XmlQualifiedName,System.Runtime.Serialization.DataContract]& knownDataContracts) [0x00000] in <3355504862ba4e7f92c25c91d98a6780>:0
    • at System.Runtime.Serialization.DataContract.ImportKnownTypeAttributes (System.Type type, System.Collections.Generic.Dictionary`2[TKey,TValue] typesChecked, System.Collections.Generic.Dictionary`2[System.Xml.XmlQualifiedName,System.Runtime.Serialization.DataContract]& knownDataContracts) [0x00228] in <3355504862ba4e
     
  6. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,674
    It looks like we never received the promised bug report. Do you mind reporting one?
     
  7. Avallach

    Avallach

    Joined:
    Jul 25, 2012
    Posts:
    1
    I have the same problem, this time with WebGL build. I am using
    DataContractJsonSerializer instead if JsonUtility as JsonUtility does not support serialization of decimals nor
    cutstom ISerializables, and I do not like how it serializes floats (e.g. 1.4999999999999999 instead of 1.5). I'm using JSON instead of binary serialization because I want human readable output.

    DataContractJsonSerializer works fine in editor, but in WebGL build construction of
    DataContractJsonSerializer throws
    Code (CSharp):
    1. ConfigurationErrorsException: Failed to load configuration section for dataContractSerializer.
    Nothing else is needed to reproduce the problem.
    If I will be unable to fix it, I'll just have to switch to ints.
     
  8. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,674
    Can we get a bug report?
     
  9. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
  10. Mgravitus

    Mgravitus

    Joined:
    Oct 8, 2015
    Posts:
    13
    Running into exact same issue. any news or update?
     
  11. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,931
    We've tracked down what is happening in this case. It is an error that we can work around without making any changes on the Unity side, so I wanted to provide information about that work around here.

    I've seen two different errors in this case, based on the Api Compatibility Level setting.

    If the Api Compatibility Level for the project is .NET 4.x, the error originally reported in this thread will occur.

    If the Api Compatibility Level for the project is .NET Standard 2.0, I see an exception that starts like this:

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object.
    2.  
    3.   at System.Runtime.Serialization.Json.JsonFormatWriterInterpreter.TryWritePrimitive (System.Type type, System.Func`1[TResult] value, System.Reflection.MemberInfo memberInfo, System.Nullable`1[T] arrayItemIndex, System.Xml.XmlDictionaryString name, System.Int32 nameIndex) [0x00000] in <00000000000000000000000000000000>:0
    If you are using Unity 2018.2 or newer, you can work around this issue by doing the following:
    1. Choose the .NET Standard 2.0 Api Compatibility Level
    2. Add a link.xml file to the Assets folder of your project with the following contents:
    Code (CSharp):
    1. <linker>
    2.        <assembly fullname="System.Runtime.Serialization" preserve="all"/>
    3. </linker>
    The problem here is that the DataContractJsonSerializer implementation in the class library assembly System.Runtime.Serialization.dll uses reflection to access some methods. The Unity managed code linker strips away these methods, and the DataContractJsonSerializer class fails to work properly. By preserving everything in System.Runtime.Serialization.dll, those methods are kept.

    Note that this is a different problem with the .NET 4.x Api Compatibility Level. That one is a little more involved. We've corrected it in 2018.3, which should be public beta soon. Prior to that release, you will need to use the .NET Standard 2.0 Api Compatibility Level to work around this issue. Once 2018.3 is available, the link.xml file provided here will still be necessary to make this work properly with either Api Compatibility Level option.
     
  12. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    Will you put some of that information here: https://issuetracker.unity3d.com/is...figuration-section-for-datacontractserializer

    the current state of closed with "By Design" with no comment from Unity is extremely frustrating especially previously it was "Workaround possible" with also no comment about how to work around it.

    Unfortunately for my project its totally not possible to to move to .NET 2 from 4 but waiting until 2018.3 is an option. Will this be fixed in the 2018.3.1 beta?

    Edit: Just found this page which seems related: https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html
     
    Last edited: Sep 3, 2018
  13. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,931
    Good point, I have added information to the public Issue Tracker page for this bug.

    The fix in the .NET 4.x compatibility level will be in the first 2018.3 beta. I curious though about what part of the .NET 4.x Api Compatibility Level you need that in not in .NET Standard 2.0. The .NET Standard 2.0 Api Compatibility Level is a pretty large subset of .NET 4.x, and contains most of the APIs we expect to be necessary for a Unity project. Can you provide specifics about what is missing? That would be rather helpful to us as we think about .NET profile support for the future.
     
  14. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    Thanks so much for adding it! <3 And great news we were able to make some minor changes and get it working with .Net 2 so all is good for us now :-D

    If I may make a suggestion - once something reported in the forums is made into a bug report have the form page "locked" and link to the bug report and have further discussion of it done on the bug report (which would also link to the forum post that triggered the bug report) - that way all the information is all in one place and no one has to worry about a bug being closed as "wont fix" or even left as "workaround possible" with further info about it back in a forum post.

    It was a little on the slow side getting info from Unity on the workaround but we definately appreciate you guys fixing the bug and finally posting the workaround info :)
     
  15. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,931
    Unfortunately I don't have any say over the forums and bug tracking workflow. But I agree, keeping the information in one place sounds like a good idea!
     
  16. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    Ok well...... everything was working until we tested on WebGL.

    This bit of code:

    Code (CSharp):
    1.         string output = "";
    2.         StageJsonDelegate stage = new StageJsonDelegate(BlockManager.Instance);
    3.         StageCollection collection = new StageCollection(stage);
    4.         CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
    5.         Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
    6.         try
    7.         {
    8.             MemoryStream ms = new MemoryStream();
    9.             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(StageCollection));
    10.             XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8, true, false);
    11.             serializer.WriteObject(writer, collection);
    12.             writer.Flush();
    13.             output += Encoding.UTF8.GetString(ms.ToArray());
    14.         }
    15.         catch (System.Exception exception)
    16.         {
    17.             LogController.Log(exception.ToString());
    18.         }
    19.         finally
    20.         {
    21.             CurrentState = State.Idle;
    22.             Thread.CurrentThread.CurrentCulture = currentCulture;
    23.         }
    the line: serializer.WriteObject(writer, collection); is thowing:

    Code (CSharp):
    1. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ExecutionEngineException: Attempting to call method 'System.Runtime.Serialization.XmlObjectSerializerWriteContext::IncrementCollectionCountGeneric<System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]>' for which no ahead of time (AOT) code was generated.
    2.  
    3. --- End of inner exception stack trace ---
    4.  
    5. at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0
    I think is having trouble serializing a Dictionary (but this is just a guess):

    Code (CSharp):
    1. [DataMember(Name="Properties",Order = 100)]
    2. public Dictionary<string, string> Properties
    AFAIK there is no way to force AOT generation for a non-public method like this correct?
     
    Last edited: Sep 11, 2018
  17. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,931
    I don't think there is a good way to force AOT generation for this non-public method. Is this the first or only IL2CPP platform where this code was used? I'm wondering if it is somehow specific to WebGL, although I would expect this on any AOT platform.
     
  18. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    Ok so the good news: I can confirm the linker xml thing works in 2018.3beta for .NET4

    The bad news: we still get the same AOT exception when trying to serialize

    *Edit* update: as expected this error is occuring on all IL2CPP platforms

    Assuming I'm reading this exception right and its an error in serializing a Dictionary<string,string> - In worst case we can probably create some kind of custom string dictionary class to work around it in our code, though I imagine serializing dictionaries is something Unity would like to fix.
     
    Last edited: Sep 13, 2018
  19. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    It is definately related to serializing a Dictionary<string,string>

    One thing that did not work: using the
    Code (CSharp):
    1. DataContractJsonSerializer(Type, IEnumerable<Type>)
    version of DataContractJsonSerializer and passing a list of types including Dictionary<string,string>

    too bad that would have been nice and easy! it threw the same exception.

    Disabling the Dictionary<string,string> field results in serialization working fine, so its just this one type messing things up.

    On a whim I tried changing the field to a List<KeyValuePair<string,string>> but got the same results. (expected since I think its the KeyValuePair part that is messing everything up)
     
    Last edited: Sep 14, 2018
  20. CatherineIrkalla

    CatherineIrkalla

    Joined:
    Sep 12, 2017
    Posts:
    14
    Ok looks like we have been able to create a workaround by changing our code to use a custom class in a list instead of dictionary. I do believe the code below allows us to keep the same JSON format while working around the AOT error (we are still testing though)

    Old code:

    Code (CSharp):
    1. [DataMember(Name = "Properties", Order = 100)]
    2. public Dictionary<string, string> Properties {
    3.       get { return _block.Properties; }
    4.  }
    New code:

    Code (CSharp):
    1. [DataMember(Name="Properties",Order = 100)]
    2.     public List<PropertyJsonDelegate> Properties
    3.     {
    4.         get
    5.         {
    6.             Debug.Assert(_block != null);
    7.             List<PropertyJsonDelegate> test = new List<PropertyJsonDelegate>();
    8.             foreach(KeyValuePair<string,string> item in _block.Properties)
    9.             {
    10.                 test.Add(new PropertyJsonDelegate(item));
    11.             }
    12.             return test;
    13.         }
    14. }
    Code (CSharp):
    1. [DataContract(Name="Property")]
    2. public class PropertyJsonDelegate
    3. {
    4.     [DataMember]
    5.     public string Key;
    6.     [DataMember]
    7.     public string Value;
    8.  
    9.     public PropertyJsonDelegate(KeyValuePair<string,string> value)
    10.     {
    11.         Key = value.Key;
    12.         Value = value.Value;
    13.     }
    14. }
     
    mciv likes this.
  21. paulstraw

    paulstraw

    Joined:
    Apr 17, 2017
    Posts:
    4
    I was running into this issue in Unity 2019.1.0f2 with .NET 4.x Api Compatibility Level selected in Player settings. Even without reverting to .NET 2.0, adding the specified `assembly` element to my link.xml as described above fixed the problem for me.
     
    MaxGuernseyIII likes this.
  22. eliGasious

    eliGasious

    Joined:
    Apr 7, 2015
    Posts:
    16
    I had this issue in 2019.1.2f1
    Work Around:
    I Replaced
    using System.Runtime.Serialization;

    with
    using System.Runtime.Serialization.Formatters.Binary;


    and used the Binary formatter instead to get basically the same functionality. Because the link.xml wasn't working as a fix for my android target platform build.
     
  23. GameDBharat

    GameDBharat

    Joined:
    Aug 12, 2017
    Posts:
    8
    i had this issue when i m trying to save my game data. I have used linker. when i am loading file from json it works fine at saving time its shows below error:
    07-01 13:05:39.463 27881-27952/com.abcd.runner I/Unity: System.ExecutionEngineException: Attempting to call method 'System.Runtime.Serialization.XmlObjectSerializerWriteContext::IncrementCollectionCountGeneric<System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]>' for which no ahead of time (AOT) code was generated.
    at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0
    at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <00000000000000000000000000000000>:0
    at System.Runtime.Serialization.Json.JsonFormatWriterInterpreter.WriteCollection (System.Runtime.Serialization.CollectionDataContract collectionContract) [0x00000] in <00000000000000000