It’s been a long time since I posted anything, hopefully, the writer’s block stops now :)
This post is about using Enums in WCF communications.
As most of you WCF developers know by now, if you are exposing an enum in your service (as a result or a paramter) the client’s generated proxy will contain the enum and everything will work perfectly fine.
Unfortunately, using enum creates some sort of coupling between the contracts of the two tiers where passing an enum value which exists in one side only would yield a serialization exception.
This means that if I create my SmartClient today and tomorrow the service author decides to add an enum value to one of the enums – all operations which would return this would suddenly fail on the client side, causing me to have to update the reference, recompile and release a new version of my client.
Obviously, this could be the other way around.
A client can add a value to the enum (admittedly, not the best thing to do). Now whenever the client calls a service operation with this value as a parameter – the operation isn’t executed and a serialization exception occurs.
While we might consider this as an acceptable behavior, I came across several projects who maintained those enums in both tiers (some of the enum values were enum members and some were not).
In these projects, we wanted a fallback value for enums so the execution will not blow up – the application/service logic would handle the unknown fallback value accordingly.
To summarize, I wanted to do something like the following:
enum SampleEnum
{
Value1,
Value2,
Value3,
[DefaultEnumMember]
Unknown
}
As the example suggests, I wanted that my service would be able to accept any value sent from the client as a ‘SampleEnum’ where in cases of non-matching value – it should fallback to ‘Unknown’.
The same goes for the usage in the client side – The enum is defined there as well and I want the exact same behavior.
Sadly, there isn’t such built-in behavior.
We can achieve this by plugging into the WCF in the right places.
There are 2 general approaches –
- Expose wrapper / surrogate contracts and handle the enum serialization / conversion within these contracts.
The main disadvantage of such pattern is that the service metadata will no longer expose a normal ordinary enum, meaning it will affect the generated proxy’s data as well.
However, we could participate in the WSDL export and import process as well to try and compensate this.
- Take part in the serialization process.
We can do this by several ways. - Write our own XmlObjectSerializer to handle the serialization ourselves and hook it up with our own operation behavior.
- Handle the message content before it gets to the serializer – check enum values, if the values are non-matched, replacing it with the default fallback value.
This can be done through message inspection or providing your own message formatter, most probably a more intuitive place.
I hope to blog more about it soon enough, when I finish the implementation.