I am experiencing issues with a WCF REST service. The wire object that I try to return has certain properties not set, resulting in DateTime.MinValue for properties of type DateTime. The service returns an empty document (with HTTP status 200 ???). When I try to call JSON serialization myself, the exception that is thrown is:
SerializationException: DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON.
This can be reproduced by running the following code in a console app:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(DateTime));
MemoryStream m = new MemoryStream();
DateTime dt = DateTime.MinValue;
// throws SerializationException in my timezone
ser.WriteObject(m, dt);
string json = Encoding.ASCII.GetString(m.GetBuffer());
Console.WriteLine(json);
Why is this behaviour? I think it is related to my timezone (GMT+1). As DateTime.MinValue is default(DateTime), I would expect that this can be serialized without problems.
Any tips on how to make my REST service behave? I don't want to change my DataContract.
Try to add this on any DateTime Member
Most of these erros happens because the default value of the
datetime
isDateTime.MinValue
which is from year of 1 and the JSON serialization is from year 1970.You could fix that during serialization via the OnSerializing attribute and some reflection:
The main problem is
DateTime.MinValue
hasDateTimeKind.Unspecified
kind. It is defined as:But this is not a real problem, this definition leads to problem during serialization. JSON DateTime serialization done through:
Unfortunately it is defined as:
So it doesn't take into account
Unspecified
and treats it asLocal
. To avoid this situation you can define your own constant:or
It looks weird of course, but it helps.
I believe a more elegant way is to instruct the serializer not to emit the default value for DateTime fields. This will save some byte during transfer and some processing when serializing for the fields that you don't have any value for them. Example:
or you can use Nullables. Example:
It all depends on the requirements and restrictions you might have in your project. Sometimes you cannot just change the data types. In that case you can still take advantage of
DataMember
attribute and keep the data types intact.In the above example if you have
new Document() { Title = "Test Document" }
in the server side, when serialized to JSON it will give you{"Title": "Test Document"}
so it will be easier to deal with in JavaScript or any other client in the other side of the wire. In JavaScript if you JSON.Parse() it, and try to read it, you will get backundefined
. In typed languages you will have the default value for that property depending on the type (which is typically the expected behavior).If your time zone is GMT+1, then the UTC value of
DateTime.MinValue
in your time zone is going to be an hour less thanDateTime.MinValue
.using this constructor:
example code: