ASP.NET Web Api, JSON y el formato de fechas

Cuando trabajamos con ASP.NET Web Api, hemos podido comprobar que si enviamos fechas en una cultura con un formato distinto al utilizado en InvariantCulture, podemos tener el problema de que el día se convierte en mes y viceversa (por ejemplo dd/MM/yyyy).

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<form>
    <fieldset>
        <legend>Web Api DateTime</legend>
        <label for="Name">Name:</label>
        <input type="text" id="Name" name="Name" value=" " />
        <label for="Birth">Birth: </label>
        <input type="text" id="Birth" name="Birth" value=" " />
        <input type="button" id="btnTest" value="Test" />
    </fieldset>
</form>

<script src="~/Scripts/jquery-2.0.3.min.js"></script>
<script>
    $(function () {

        $("#btnTest").click(function () {

            $.ajax({
                url: '/api/values',
                type: 'POST',
                dataType: 'json',
                data: { 'Name': $("#Name").val(), 'Birth': $("#Birth").val() }

            }).then(function (result) {

                alert(result);

            });
        });

    });
</script>

Web Api Json Dates Wrong

Si buscas por Google, principalmente la solución que aportan es crear un custom date handling para Newtonsoft, pero lo cierto es que cuando trabajas con diferentes culturas no es una solución muy viable, por lo que es necesario encontrar algo más (quizás en el lado del cliente).

La solución que, personalmente, creo que es la más elegante es hacer uso del formato ISO 8601: YYYY-MM-DDThh:mm:ss.sTZD (ejemplo: 1997-07-16T19:20:30.45+01:00). De esta manera, nos aseguramos de que todas las fechas que enviamos a nuestro servicio web llegan en un formato donde no hay posibilidad de equivocación por parte del back end.

Para conseguirlo he modificado el código anterior de la siguiente manera:

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<form>
    <fieldset>
        <legend>Web Api DateTime</legend>
        <label for="Name">Name:</label>
        <input type="text" id="Name" name="Name" value=" " />
        <label for="Birth">Birth: </label>
        <input type="text" id="Birth" name="Birth" value=" " />
        <input type="button" id="btnTest" value="Test" />
    </fieldset>
</form>

<script src="~/Scripts/jquery-2.0.3.min.js"></script>
<script src="~/Scripts/moment.min.js"></script>
<script>
    $(function () {

        $("#btnTest").click(function () {

            var date = moment($("#Birth").val(), "DD/MM/YYYY");

            $.ajax({
                url: '/api/values',
                type: 'POST',
                dataType: 'json',
                data: { 'Name': $("#Name").val(), 'Birth': date.toISOString() }

            }).then(function (result) {

                alert(result);

            });
        });

    });
</script>

Web Api Json Dates Right

En primer lugar, estoy utilizando la librería Moment.js, la cual nos permite de una forma sencilla obtener un objeto de tipo Date, pasándole como parámetro el formato correcto de nuestra fecha en cliente. Este segundo parámetro podríamos obtenerlo de las librerías que utilicemos para modificar la cultura actual del usuario.

Si por ejemplo utilizamos un datepicker, como puede ser el de JQuery UI, podríamos conseguirlo de la siguiente manera:

var date = $.datepicker.formatDate($.datepicker.ISO_8601, date);

De esta forma logramos que nuestra información sea la correcta, independientemente de la cultura con la que estemos trabajando.

Espero que sea de utilidad.

¡Saludos!