miércoles, 22 de marzo de 2017

¿Asignar CurrentCulture al ModelState de MVC? ¿Está seguro doctor? El caso de las fechas invalidables.

Nuestro paciente en ocasiones no digería bien las fechas presentando graves reacciones alérgicas además, presentaba una grave desorientación espacial sin ser capaz de asociar a qué país viajaba.

Notábamos que si metíamos una fecha a un controller, usualmente mediante un datepicker de jquery o bootstrap observábamos que para unos formatos culturales ModelState validaba bien y para otros no, a pesar de que el string de la fecha está perfecto.

Cuando examinábamos ModelState a ver qué tenía, veíamos que la cultura actual del sistema no correspondía con la de ModelState, causando el problema.

Cultura actual: "es-ES", y sin embargo: 



Explicamos cómo se trata en estos casos al paciente.

Cuando sucede esto es común preguntar en google sobre cómo hacer que ModelState tenga siempre la cultura actual, llegando a la conclusión de que esto no es posible de llevar a cabo pues MVC siempre utilizará InvariantCulture para pasar valores desde una vista a un controlador, parece raro pero si nos paramos a pensarlo es la manera más óptima.

Para que las fechas encajen con la región cultural actual es necesario utilizar InvariantCulture, o siempre tendremos problemas.

Además, conviene que el datepicker que utilicemos forme bien los strings de las fechas.

De modo que cuando pongamos un input para fechas en nuestro html haremos lo siguiente en el cshtml:

<div class="form-group">
                    <div class="control-label col-md-2">
                        <b>@NSVWeb.Resources.Literals.FieldFechaTasacion:</b>
                    </div>
                    <div class="col-md-10 input-group">
                        <label for="date-picker-1" class="input-group-addon btn">
                            <span class="glyphicon glyphicon-calendar" id="date-picker-btn-1"></span>
                        </label>
                        @Html.TextBoxFor(model => model.FechaTasacion,
    new
    {
        @Value = Model.FechaTasacion.ToString("d", System.Globalization.CultureInfo.InvariantCulture),
        @Class = "date-picker form-control"
    })
                        @Html.ValidationMessageFor(model => model.FechaTasacion, "", new { @class = "text-danger" })
                    </div>
                </div>


Para conseguir que el datepicker tome el formato de fecha de la cultura actual, simplemente se la pasaremos por un input hidden:

<input type="hidden" id="currentDateTimeFormat" value="@System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.ShortDatePattern.ToLower()" />

Y la tomaremos para el datepicker en el .js:

$(".date-picker").datepicker({
    format: $('#currentDateTimeFormat').val(),
    showOtherMonths: true,
    selectOtherMonths: true,
    autoclose: true,
    changeMonth: true,
    changeYear: true,
});


No hay comentarios: