Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Versioning Enums

I'm beginning writing some WCF data contracts that need to be forward-compatible & versionable. I've been reading the MSDN article here, and was wondering if anyone has clarification on point #14 regarding enums. It reads as follows:

14. You should not add or remove enumeration members between versions. You should also not rename enumeration members, unless you use the Name property on the EnumMemberAttribute attribute to keep their names in the data contract model the same.

Reading this, I take it to mean that once an enum is published (and used by clients), you you cannot modify it in anyway (adding / removing mainly) without breaking compatibility? (i.e. this would be a breaking change)

Can someone confirm this?

like image 409
Gareth Avatar asked Jan 13 '11 07:01

Gareth


2 Answers

I'd recommend not sending enums over WCF interfaces. Suppose you have the following enum:

[DataContract]
public enum WeekdayEnum
{
    [EnumMember]
    Monday = 0
}

If you return the enum over WCF, everything will work well:

[ServiceContract]
public class Service1
{
    [OperationContract]
    public List<WeekdayEnum> GetWeekdays()
    {
        return new List<WeekdayEnum> { WeekdayEnum.Monday };
    }
}

Add to the enum without updating the Service Reference in the client and you're still fine:

[DataContract]
public enum WeekdayEnum
{
    [EnumMember]
    Monday = 0,
    [EnumMember]
    Tuesday = 1
}

However, if you return the added value from the service without updating the client Service References, the legacy clients will break:

[ServiceContract]
public class Service1
{
    [OperationContract]
    public List<WeekdayEnum> GetWeekdays()
    {   // NetDispatcherFaultException on legacy clients that only have Monday
        return new List<WeekdayEnum> { WeekdayEnum.Monday, WeekdayEnum.Tuesday };
    }
}

I've had issues with this in projects where supporting legacy clients is important. The solution has been to simply send DTOs over the WCF instead of enums. E.g. the WeekdayEnum could be replaced by sending the values over a simple DTO:

[DataContract]
public class WeekdayDto
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

This way, your legacy clients stay happy.

like image 181
Lauri Harpf Avatar answered Oct 12 '22 23:10

Lauri Harpf


I can confirm that you can ADD to a published enum without breaking compatibility, as long as you don't use the new value when talking to the service. However be aware that if you actually try to send an class to the service that is using the new enum value, you will get a System.ServiceModel.CommunicationException.

There was an error while trying to serialize parameter myType. The InnerException message was 'Enum value 'x' is invalid for type 'myType' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'.  Please see InnerException for more details.
like image 30
Ryan Sorensen Avatar answered Oct 13 '22 00:10

Ryan Sorensen