Do you use enum types in your WCF web services?

I've heard some people saying that enums are evil and shouldn't be used in web services because of the mismatches that could occur between the server and the client if some values are assigned, or if the enum is marked with the Flags attribute. They also said that web services exposing enums are harder to maintain but couldn't really give me viable arguments. So from your experience what are the pros and cons of using enums in a WCF web service?


Solution 1:

The reason people recommend to avoid enums in webservices is because they create subtle backwards compatible problems.

The same applies to regular enums but in web services the problem is even more clear specially in .NET-generated proxies (see below).

  • If the enumerate is input only you have no issues.
  • If the enumerate can be an out parameter then if you add a new element and you return it, old clients could have problems:
    • If the client is using a .NET-generated proxy it will break before the caller can handle it (in the deserialization)
    • Even if the generated code for the proxy supported the change (for example if it maps the enumerate to a string) the user code in the client may not process properly the new unexpected value (it could easily be a never executed path)

By defining the parameter as a string you signal the user of your API that the value may change in the future. Even if you think that the value will never change is a good practice to be ready.

There is a good post by Dare Obasanjo on this topic.

Solution 2:

I have used enums in WCF, also in interoperability scenarios. If you control both sides of the service, it is easier to work with. If you only control one side of the service, you need to look out for the issues that you mentioned.

Enums are so much better that string variables, or what else you might choose to use. Using strings instead of enums is an anti pattern called "loosey Goosey" in SOA.

Solution 3:

Enumerations are fully supported in WSDL and XSD through the xsd:enumeration schema element. It provides support for both single values and flags-style enumerations, where multiple values in a flags enumeration are separated by spaces.

So you should have no problem using enumerations with any standards compliant platforms.

Solution 4:

Of course, it all depends on where you are going to use this WCF service.

If it's a single application that will use it, then changing the contract won't have any effects.

If it's multiple internal applications, changing the contract might require some changes on the other applications.

And finally, if the WCF service is public, you might have to provide 2 versions of the service with differents version so that the people consuming them have the time to transfer their version of the client to the new service.

It all depends on your needs honestly.

Solution 5:

Using anything else but enums does not solve your compatibility issue, it only hides it. Assume you use an int to replace an enum. Did you really solve the compatibility issue or just disguised it until the client runtime hits the unknown value?

However, one thing is worth mentioning: WCF proxies do not recreate explicitly set enum numeric values. If the enum is declared with "holes", like

enum ErrorCodes
{
  OK = 0,
  GenericError = 100,
  SomeOtherError = 101,
}

the client side representation will be like this

enum ErrorCodes
{
  OK,
  GenericError,
  SomeOtherError,
}

... which on the client results in (int)ErrorCodes.GenericError being 1.

You'll have syntactic equivalence, but not numeric equivalence.