Friday, 4 October 2013

C# Enum XML Serialization - Instance validation error: 'value' is not a valid value for ObjectType.

When using serialization in C# I've found a very annoying problem that doesn't seem to have a good solution. If you rename or remove an enum value the XML serializer reports the following error when you try and deserialize and existing object that uses that enum value.

Instance validation error: 'value' is not a valid value for ObjectType.

I already use code to standardise enums to "Unknown" on the set accessor if an unknown value is passed in. This however isn't good enough for the XML serializer which pre-checks all possible values.

Take the following example where bicycle has been spelled incorrectly but we already have XML data in customer environments with the incorrect spelling so we can't just rename it.
 

/// <summary>
/// The type of vehicle.
/// </summary>
public enum VehicleType
{

    /// <summary>
    /// The vehicle type is unknown.
    /// </summary>
    Unknown,

    /// <summary>
    /// A normal car.
    /// </summary>
    Car,

    /// <summary>
    /// A bike.
    /// </summary>
    Bicyle,

}


I wanted to override the serialization process to correct the value however this doesn't seem possible. I looked at IXmlSerializable however this looked way too much complexity.

You have the simple option of adding another value however then using intellisense you get

VehcileType.Bicyle and VehicleType.Bicycle next to each other which makes it likely you'll make a mistake in enum selection.

I looked at adding the [Obsolete] attribute to the incorrect spelling however the XML serializer automatically ignores values marked as obsolete....

The workaround I completed was as follows

  • Rename the incorrect enum value with a nice obvious obsolete prefix
  • Use the XmlEnum attribute to use the spelling mistake
  • Use the property accessor for the enum to correct the value
This isn't ideal but it does mean the XML serializer doesn't break and values will be corrected over time and then the property can be removed. I hope this is useful to someone else as this problem is really quite annoying!


/// <summary>
/// The type of vehicle.
/// </summary>
public enum VehicleType
{

    /// <summary>
    /// The vehicle type is unknown.
    /// </summary>
    Unknown,

    /// <summary>
    /// A normal car.
    /// </summary>
    Car,
 
    /// <summary>
    /// WARNING: this property is obsolete.
    /// </summary>
    [XmlEnum("Bicyle")]
    ObsoleteBicyle,

    /// <summary>
    /// A bike.
    /// </summary>
    Bicycle,
 
}




/// <summary>
/// Gets or sets the type of vehicle
/// </summary>
public VehicleType VehicleType
{
    get { return _VehicleType; }
    set
    {
        if (value == xmltest.VehicleType.ObsoleteBicyle) { value = xmltest.VehicleType.Bicycle; }
        _VehicleType = value;
    }
}
private VehicleType _VehicleType = VehicleType.Unknown;



No comments:

Post a Comment