Skip to content

Latest commit

 

History

History
109 lines (92 loc) · 4.39 KB

PX1064.md

File metadata and controls

109 lines (92 loc) · 4.39 KB

PX1064

This document describes the PX1064 diagnostic.

Summary

Code Short Description Type Code Fix
PX1064 The declaration of the exception class introduces new serializable fields but does not declare an override for the GetObjectData method. This will cause incorrect serialization of the exception data and will lead to runtime errors in Acumatica ERP. Error Available

Diagnostic Description

Every class that is derived from the System.Exception class (including PXException-derived classes) and that declares new serializable data should always provide an override for the GetObjectData method.

This diagnostic considers data to be serializable if it is new data declared in the exception class that will be serialized by .Net serializers and Acumatica reflection-based serializers. This data includes the following:

  • New instance fields if they are not marked with the System.NonSerializedAttribute attribute
  • New automatically generated instance properties if they are not marked with the System.NonSerializedAttribute attribute

For example, the following types of members are not considered serializable:

  • Static fields and constants
  • Static properties
  • Calculated properties
  • Properties with an explicit backing field, as shown in the following example
    public int Property 
    {
       get =>  _fieldFromBaseClass;
       set 
       {
    	   _fieldFromBaseClass = value;
       }
    }
  • Fields and properties marked as non-serializable, as shown in the following example
    [field: NonSerialized]
    public int Property { get; set; } 

The code fix generates the missing GetObjectData method override that contains the following statements:

  1. A call to the GetObjectData static method of the PX.Common.ReflectionSerializer class. This class is responsible for Acumatica reflection-based serialization and deserialization of data.
  2. A call to the base GetObjectData method, as shown in the following example.
    base.GetObjectData(info, context);

Note: In older versions of Acumatica ERP, there is no PX.Common.ReflectionSerializer class because it was added later during refactoring. The PX.Common.PXReflectionSerializer class will be used instead; the names of the methods are the same.

Example of Incorrect Code

public sealed class PXNewSerializableAutoPropertiesException : PXBaseRedirectException
{
	/// <summary>
	/// Identifier of the document that should be signed
	/// </summary>
	public Guid FileId { get; private set; }
	/// <summary>
	/// View name from which the sign action is called
	/// </summary>
	public string ViewName { get; private set; }

	public PXNewSerializableAutoPropertiesException(string viewName, Guid fileId) : base(fileId.ToString())
	{
		ViewName = viewName;
		FileId = fileId;
	}

	private PXNewSerializableAutoPropertiesException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
	{
		FileId = (Guid)info.GetValue(nameof(FileId), typeof(Guid));
		ViewName = info.GetString(nameof(ViewName));
	}
}

Example of the Code Fix

public sealed class PXNewSerializableAutoPropertiesException : PXBaseRedirectException
{
    /// <summary>
    /// Identifier of the document that should be signed
    /// </summary>
    public Guid FileId { get; private set; }
    /// <summary>
    /// View name from which the sign action is called
    /// </summary>
    public string ViewName { get; private set; }

    public PXNewSerializableAutoPropertiesException(string viewName, Guid fileId) : base(fileId.ToString())
    {
        ViewName = viewName;
        FileId = fileId;
    }

    private PXNewSerializableAutoPropertiesException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
    {
        FileId = (Guid)info.GetValue(nameof(FileId), typeof(Guid));
        ViewName = info.GetString(nameof(ViewName));
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        ReflectionSerializer.GetObjectData(this, info);
        base.GetObjectData(info, context);
    }
}