Control fails to load with serialization issue when upgrading Framework project to .NET 6
- Dominant language
- C#
- Stars
- 4.9k
- Forks
- 1.1k
- Avg merge
- 20h 23m
- Merged PRs (30d)
- 103
Description
### .NET version
.NET 6.0.20
.NET 8.0.0 Preview 6
### Did it work in .NET Framework?
Yes
### Did it work in any of the earlier releases of .NET Core or .NET 5+?
_No response_
### Issue description
Hello,
I wasn't sure if this is the correct repository to create this issue, but I have been running into a problem migrating a large WinForms .NET Framework project to .NET 6 and eventually .NET 8.
My first step was to convert all of the .csproj files into the SDK style format, which I used the upgrade-assistant dotnet tool to accomplish, and with some manual adjustments I was able to get everything converted and running. I am able to build my solution and get my project up and running with some visual artifacts that I will have to fix.
Now my problem I am encountering has to do with the designer and how it stores public properties into the resource .resx file within my Controls and Forms. In .NET Framework, our public properties are being stored and binary serialized into the resx file for the form/control, but since the upgrade to .NET 6, most of them are failing to deserialize when opening the designer and are giving the following error.
> Unable to find assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
> at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
> at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
> at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
> at System.Runtime.Serialization.Formatters.Binary.BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
> at System.Runtime.Serialization.Formatters.Binary.BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
> at System.Runtime.Serialization.Formatters.Binary.BinaryParser.Run()
> at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(BinaryParser serParser)
> at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
> at Microsoft.DotNet.DesignTools.Utilities.Resources.ResXDataNode.GenerateObjectFromDataNodeInfo(DataNodeInfo dataNodeInfo, ITypeResolutionService typeResolver)
> at Microsoft.DotNet.DesignTools.Utilities.Resources.ResXDataNode.GetValue(ITypeResolutionService typeResolver)
> at Microsoft.DotNet.DesignTools.Utilities.Resources.ResXResourceReader.ParseDataNode(XmlTextReader reader, Boolean isMetaData)
> at Microsoft.DotNet.DesignTools.Utilities.Resources.ResXResourceReader.ParseXml(XmlTextReader reader)
Looking further into this, one example I came across was that our public property at design time is an empty List\, and upon further inspection of the resx file for the form which contains the value of the property differs between .NET Framework and .NET 6. The example below is from my sample application I have attached.
```
AAEAAAD/////AQAAAAAAAAAMAgAAAJoBbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1u
ZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0sIG1zY29ybGliLCBWZXJzaW9u
PTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQUB
AAAAL1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLkludDMyAwAAAAZfaXRl
bXMFX3NpemUIX3ZlcnNpb24HAAAICAgCAAAACQMAAAAAAAAAAAAAAA8DAAAAAAAAAAgL
```
```
AAEAAAD/////AQAAAAAAAAAEAQAAAH5TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5
c3RlbS5JbnQzMiwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJs
aWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0DAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgcAAAgI
CAkCAAAAAAAAAAAAAAAPAgAAAAAAAAAICw==
```
It looks like the binary serializer has changed between these two frameworks, but I don't believe that is the case. I have tried taking the base64-encoded string generated by the .NET Framework designer and tried to manually deserialize it with code within my .NET Framework project and I encounter the same error. I do not encounter the error with the .NET 6 version of the base64-encoded binary string in either .NET Framework or .NET 6. I believe the designer in .NET Framework is adding something else that cannot be deserialized without going through the resources.GetObject() method within the designer, and that will be a problem for anyone going through the same upgrade process as myself.
I can manually fix most of these with a find/replace using the sample project I created since they are empty lists in our case, but we do have some where some data has been manually inputted into the collection, so doing a simple find/replace isn't going to work here.
There is a vaguely similar issue that I found that could be related to this problem. https://github.com/dotnet/winforms/issues/8584
### Steps to reproduce
I will attach a sample Visual Studio solution demonstrating this issue. Inside of the solution there will be 4 WinForms projects:
[ResXPropertySerialization.zip](https://github.com/dotnet/winforms/files/12197916/ResXPropertySerialization.zip)
- one with the old csproj format using .NET Framework 4.8
- one that was an old csproj format using.NET Framework 4.8 but upgraded with upgrade-assistant to .NET 6
- one that is a new SDK csproj format using 'net48'
- one that is a new SDK csproj format using 'net6.0-windows'
Each project has one Form and one Control, where the Form has the control inside of it. All of the projects open up in the respected designer (in/out of process) with the exception of the one that was converted using upgrade-assistant, which throws the error.
You can replicate this error with my sample application by updating the third project that is the SDK style csproj targetting 'net48' and changing that to 'net6.0-windows', building the solution, then trying to open the form with the designer in the project.
Contributor guide
Assessment
This issue has not been assessed yet.