Serialization breaks in .NET 4.5

15,347

Solution 1

In 4.5, the implementation of XmlSerializer was replaced with one that isn't dependent on the C# compiler. While it provides better startup performance and stability, you might be running into a compatibility issue between the implementations. Can you try adding the following to your app.config file and see if that fixes the issue?

<configuration>
  <system.xml.serialization>
    <xmlSerializer useLegacySerializerGeneration="true"/>
  </system.xml.serialization>
</configuration>

If you're concerned about having this work on 4.0, you could try detecting the version of the framework at runtime, and dynamically change the configuration if the runtime is 4.5 or higher. I wrote a blog post a while back explaining how to do that:

http://blogs.msdn.com/b/youssefm/archive/2010/01/21/how-to-change-net-configuration-files-at-runtime-including-for-wcf.aspx

Solution 2

We're looking to address this issue in upcoming .NET Framework 4.5 Update. I'll update the post with the download link as soon as update is released. Please contact netfx45compat at Microsoft dot com if you have mission critical app that's impacted, and fix is required urgently. I can help direct you to Microsoft support that can help with your request.

Solution 3

I had a also such a serialization failure. In my case it was caused by a type mismatch of the [DefaultValue(..)] attributes. I had an attached default value of "1.0d" (a double) for a property of type decimal. It seems that the new implementation of the XmlSerializer can't convert such values anymore but the old one could. There is also the option to switch back to the old version of XmlSerializer by adding an attribute in 'App.config' but this is not recommended by Microsoft (and me). Hope this helps someone.

Solution 4

I looked at your types more closely, and the problem is likely caused by a conflict between:

public virtual object @Value
{
}

on the Base and:

private new object Value
{
}

on the Derived class. Here are two things I would try:

  1. Try making the "new object Value" public. There might be a member access problem.
  2. Try renaming the Base's "@Value" to something like "BaseValue" or some other appropriate name. There might be a problem with your use of the '@' sign.
Share:
15,347
omer schleifer
Author by

omer schleifer

Updated on June 16, 2022

Comments

  • omer schleifer
    omer schleifer almost 2 years

    We have a serialization issue which only happens in .NET 4.5 - same code works fine in .NET 4. we're trying to serialize an inherited type with a few fields, both base and inherited class are marked with SerializableAttribute. We get an exception on the client side of Web service saying that there was a MethodAccessException in the server , the server itself does not throw any exceptions , it seems to be a problem in the client serialization process. It is important to note that we are compiling in .NET 4- not .4.5

    Update: After implementing the ISerailize and ignoring the "Value" property the program did run correctly, but it means we had to give up on serializing this field.

    any help would be most appreciated. Thanks, Omer

    The exception details:

    System.Web.Services.Protocols.SoapException occurred
      HResult=-2146233087
      Message=System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.MethodAccessException: Attempt by method 'Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write88_DeviceSiteTypeInfo(System.String, System.String, IOSIGHT.Info.DeviceSiteTypeInfo, Boolean, Boolean)' to access method 'IOSIGHT.Info.DeviceSiteTypeInfo.get_Value()' failed.
       at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write88_DeviceSiteTypeInfo(String n, String ns, DeviceSiteTypeInfo o, Boolean isNullable, Boolean needType)
       at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1310_GetSiteTypesResponse(Object[] p)
       at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer2089.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
       at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
       --- End of inner exception stack trace ---
       at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
       at System.Web.Services.Protocols.SoapServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)
       at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)
       at System.Web.Services.Protocols.WebServiceHandler.Invoke()
       --- End of inner exception stack trace ---
      Source=System.Web.Services
      Actor=""
      Lang=""
      Node=""
      Role=""
      StackTrace:
           at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
           at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
           at IOSIGHT.BLL.localhost.IOSightWS.GetSiteTypes() in C:\IOSIGHT\Common\IOSight.BLL\Web References\localhost\Reference.cs:line 25019
           at IOSIGHT.BLL.TypeBankBLL.GetSiteTypes() in C:\IOSIGHT\Common\IOSight.BLL\Entities\TypeBanksBLL.cs:line 477
      InnerException: 
    

    Attached is the base and inherited classes code: Base:

    [Serializable()]
    public class TypeBankInfo
    {
    
    
        #region "Fields"
        private int _id = 0;
        private string _Name = string.Empty;
        private string _description = string.Empty;
        private object _value = null;
    
        #endregion
    
        #region "Constructors"
        public TypeBankInfo()
        {
        }
    
        public TypeBankInfo(int ID, string name)
            : this()
        {
            this._id = ID;
            this.Name = name;
        }
    
        public TypeBankInfo(int ID, string name, string description)
            : this(ID, name)
        {
            this._description = description;
            this._value = Value;
        }
    
        public TypeBankInfo(int ID, string name, string description, object value)
            : this(ID, name, description)
        {
            this._value = value;
        }
    
        #endregion
    
        #region "Properties"
        public virtual string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                this._Name = value;
            }
        }
    
        public virtual string Description
        {
            get
            {
                return _description;
            }
            set
            {
                _description = value;
            }
        }
    
        public virtual int ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = int.Parse(value.ToString());
            }
        }
    
    
        public virtual object @Value
        {
            get
            {
                return this._value;
            }
            set
            {
                this._value = value;
            }
        }
    
        #endregion
    
    }
    

    Intheried:

    [Serializable()]
    public class DeviceSiteTypeInfo : TypeBankInfo, ISerializable
    {
    
    
        #region "Fields"
        private EntityTypeEnum _entitytype = EntityTypeEnum.Site;
        private DeviceIOTemplateInfo[] _IOTemplates;
        private CaptionInfo[] _Captions;
        private int _parentClassID;
        #endregion
    
        #region "Constructors"
        public DeviceSiteTypeInfo()
        {
        }
    
        public DeviceSiteTypeInfo(int id, string name)
            : base(id, name)
        {
        }
    
        public DeviceSiteTypeInfo(int id, string name, string description)
            : base(id, name, description)
        {
        }
    
        // The special constructor is used to deserialize values. 
        public DeviceSiteTypeInfo(SerializationInfo info, StreamingContext context)
        {
            //parent  fields
            ID = (int)info.GetValue("_id", typeof(int));
            Name = (string)info.GetValue("_Name", typeof(string));
            Description = (string)info.GetValue("_description", typeof(string));
    
    
            //my fields
            _entitytype = (EntityTypeEnum)info.GetValue("_entitytype", typeof(EntityTypeEnum));
            _IOTemplates = (DeviceIOTemplateInfo[])info.GetValue("_IOTemplates", typeof(DeviceIOTemplateInfo[]));
            _Captions = (CaptionInfo[])info.GetValue("_Captions", typeof(CaptionInfo[]));
            _parentClassID = (int)info.GetValue("_parentClassID", typeof(int));
    
        }
    
    
    
        #endregion
    
        #region "Properties"
        public EntityTypeEnum EntityTypeID
        {
            get
            {
                return this._entitytype;
            }
            set
            {
                this._entitytype = value;
            }
        }
    
    
    
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        private new object Value
        {
            get
            {
                return base.Value;
            }
            set
            {
                base.Value = value;
            }
        }
    
        public CaptionInfo[] Captions
        {
            get
            {
                return this._Captions;
            }
            set
            {
                this._Captions = value;
            }
        }
    
        public DeviceIOTemplateInfo[] IOTemplates
        {
            get
            {
                return this._IOTemplates;
            }
            set
            {
                this._IOTemplates = value;
            }
        }
    
        public int ParentClassID
        {
            get
            {
                return this._parentClassID;
            }
            set
            {
                this._parentClassID = value;
            }
        }
    
        #endregion
    
    
        #region Methods
    
       /// <summary>
       /// Called on serialization
       /// </summary>
       /// <param name="info">serialiation info</param>
       /// <param name="context">context</param>
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            // parent fields
            info.AddValue("_id", ID, typeof(int));
            info.AddValue("_Name", Name, typeof(string));
            info.AddValue("_description", Description, typeof(string));
    
            //my fields
            info.AddValue("_entitytype", _entitytype, typeof(EntityTypeEnum));
            info.AddValue("_IOTemplates", _IOTemplates, typeof(DeviceIOTemplateInfo[]));
            info.AddValue("_Captions", _Captions, typeof(CaptionInfo[]));
            info.AddValue("_parentClassID", _parentClassID, typeof(int));
        }
    
        #endregion
    
    }
    
  • omer schleifer
    omer schleifer over 11 years
    Thanks for your suggestion. I am compiling my code in .NET 4 , not .NET 4.5 - so this attribute is not applicable for me. The problem is with the "Value" property, I suspect that its attributes are not serialized correctly
  • svick
    svick over 11 years
    @omerschleifer Are you sure it's not applicable? Even if you compile for .Net 4.0, your code will actually run under .Net 4.5 if it's installed.
  • omer schleifer
    omer schleifer over 11 years
    Thank you , this does help. it also prevents the visual studio crash which is created by the same serialization issue in debug sessions , at the server side. However, since we are compiling in .NET 4 , and this code is under source control , any computer not under .Net 4.5 fails to load the config file. same goes for costumers which hadn't install the .NET 4.5 framework
  • Youssef Moussaoui
    Youssef Moussaoui over 11 years
    I've updated the answer. You can detect if 4.5 is installed with this answer: stackoverflow.com/questions/199080/…. You might also be able to check the minor version of mscorlib.
  • mbx
    mbx over 8 years
    still broken as of .net 4.6, support.microsoft.com/en-us/kb/2748720 does not help - still get FileNotFoundException for the on-the-fly-to-be-generated assembly when using XmlSerializer