I have a service which uses Noda Time types (LocalDate
and ZonedDateTime
) in OperationContract parameters, but when I try sending for example LocalDate(1990,7,31)
the server receives an object with the default value (1970/1/1). No error is thrown by the client or the server.
Previously it worked well with the corresponding BCL types (DateTimeOffset
). I understand Noda Time types may not be "known" by WCF, but I don't see how I am supposed to add them. I checked this page in the documentation about known types, but it does not help.
Is there any way to do this to avoid a dirty (and possibly incomplete) manual conversion/serialization from and to a BCL type?
Thank you.
Thanks to Aron's suggestion, I was able to come up with an implementation of IDataContractSurrogate, which is very helpful to pass objects of non base types through WCF (not only Noda Time).
For those who are interested, here is the complete code with explanations, supporting LocalDate, LocalDateTime and ZonedDateTime. The serialization method can of course be customized to meet the requirements, for example using Json.NET serialization, as my simple implementation will not serialize era/calendar information.
Alternatively, I have posted the full code on this Gist: https://gist.github.com/mayerwin/6468178.
First, the helper class that takes care of serializing/converting to base types:
Then a
ReplacementType
class which contains the serialized data (Serialized should only store types that are known by the WCF serializer) and can be passed over WCF:The serialization/deserialization rules are wrapped in
Translator
generic classes to simplify adding rules to the surrogate (only one surrogate is assigned to the service endpoint so it should contain all the necessary rules):Finally the surrogate class, each translation rule can be easily added in the static constructor:
And now to use it, we define a service named
SurrogateService
:To run on a completely standalone basis with the client and server on the same machine (in a Console application), we just need to add the following code to a static class and call the function
Start
():Voilà ! :)