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
}
Serialization is a process of converting an object into a stream of data so that it can be is easily transmittable over the network or can be continued in a persistent storage location. This storage location can be a physical file, database or ASP.NET Cache.
Basic and custom serialization Binary and XML serialization can be performed in two ways, basic and custom. Basic serialization uses . NET to automatically serialize the object.
It is not future-proof for small changes If you mark your classes as [Serializable] , then all the private data not marked as [NonSerialized] will get dumped. You have no control over the format of this data. If you change the name of a private variable, then your code will break.
Serialization in C# is the process of converting an object into a stream of bytes to store the object to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With