I created a WCF web service that implements a method that returns an object containing a DateTime value (not nullable, according to spec, don’t ask).
The web service worked fine, and I wanted to add GET support using the WebGet attribute and some web.config magic. Still worked fine.
Then I tried out some failure scenarios (if you have a status query that tries to connect to a database which happens to be offline, or misconfigured, you want to know how your status query behaves), and suddenly the only response I got from the browser was “connection reset”.
After switching on WCF tracing, the failing WCF call generated a 168kB XML file containing 160 lines of stack trace for a single call!
Despite its size, the information in the file is quite useful, as it pointed to an internal exception:
System.Runtime.Serialization.SerializationException
DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON.
at System.Runtime.Serialization.Json.JsonWriterDelegator.WriteDateTime(DateTime value) at WriteTimestampTOToJson(XmlWriterDelegator , Object , XmlObjectSerializerWriteContextComplexJson , ClassDataContract , XmlDictionaryString[] ) at System.Runtime.Serialization.Json.JsonClassDataContract.WriteJsonValueCore(XmlWriterDelegator jsonWriter, Object obj, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.Json.XmlObjectSerializerWriteContextComplexJson.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph) at System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph) at System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter writer, Object graph) at System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.SingleParameterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer) at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) at System.ServiceModel.Channels.JsonMessageEncoderFactory.JsonMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) at System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message) at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout) at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout) at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)
with an internal exception of type System.ArgumentOutOfRangeException:
Specified argument was out of the range of valid values.
Parameter name: value
and many more stack traces.
Back to my code: If there is an error connecting to the database, I return an object that contains a field set to DateTime.MinValue.
It seems that MinValue causes problems when converted to or from UTC, or at least the subsequent JSON serialization does, even though the ECMA Date range is greater than the .Net DateTime range.
Whatever the causes of this boundary problem are, returning DateTime.MinValue.AddDays(1) solved the problem.