La Excepción Fantasma
O de cómo investigar problemas WCF…
Consumiendo un servicio web preparado para generar respuestas JSON, comenzamos a obtener una excepción del tipo System.ServiceModel.CommunicationException. El detalle de la excepción es el siguiente:
System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly.
---> System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
[Se ha cerrado la conexión subyacente, en español]
Tras revisar concienzudamente las trazas del lado del servicio, visores de eventos, logs de IIS y todo lo que se nos pasa por la cabeza, certificamos que dentro del propio servicio no existía error alguno que pudiera provocar esa excepción, vamos que estábamos ante una excepción fantasma.
Estaba claro que algo se nos estaba escapando. Para continuar con el diagnóstico, no hubo más remedio que echar mano de las trazas de WCF. Para ello agregamos la siguiente configuración al web.config del servicio:
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\log\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Realizamos unas cuantas peticiones al servicio y recuperamos el archivo de trazas para abrirlo con el visor de trazas de WCF.
Como podemos observar en la imagen anterior, cuando se activan las trazas de WCF se genera mucha información muy útil para comprender el funcionamiento interno de las peticiones y respuestas a servicios WCF. En el caso que nos ocupa, vemos que en el procesamiento de la petición se está produciendo una excepción.
Accediendo al detalle del error vemos que el problema se está produciendo en la serialización de una fecha a formato JSON:
El mensaje del error nos aclara el problema:
DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON.
O lo que es lo mismo, los valores DateTime que al convertirse a UTC provoquen fechas no válidas, no se pueden serializar a JSON.
Tras revisar el código del servicio encontramos un objeto con una propiedad DateTime que se inicializa como MinValue por defecto. Para evitar el problema simplemente cambiamos la propiedad de manera que se almacene la fecha en formato UTC, inicializándolo con DateTime.MinValue.ToUniversalTime()
Conclusión
Es más que recomendable convertir a formato Utc las fechas que formen parte de objetos que se vayan a transportar en formato JSON.
Si quieres, puedes descargar el proyecto donde poder reproducir el problema de manera aislada.
Abreviaturas:
JSON: JavaScript Object Notation
WCF: Windows Communication Foundation
UTC: Universal Time Coordinated