c# - net - validar campos formulario mvc
La validaciĆ³n MVC/JQuery no acepta comas como separador decimal (3)
Actualización 07.01.2018
Aunque se sugirió que este es más un problema de jQuery que un problema de MVC, creo que es un problema de MVC.
He creado toda la aplicación en asp.net core 2.0 MVC y el error persiste.
Lo que lo vincula a MVC para mí es el hecho de que puedo resolver el problema de validación de fecha agregando la línea
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
al modelo.
Por lo tanto, MVC tiene una influencia en la validación.
Así que supongo que hay alguna forma en MVC para solucionar esto (ver esta
post
).
Por favor, publique respuestas para asp.net core 2.0.
Publicación original
En una página MVC5 renderizo una propiedad
Double
en un cuadro de texto.
Cuando se carga la página, el valor se muestra con un "," como separador decimal, lo cual es correcto, ya que la página se ejecuta en un sistema alemán.
Si quiero guardar el formulario, recibo un error de validación.
¿Cómo se puede resolver esto?
Sé que hay algunas preguntas sobre el tema, pero por lo que puedo ver, la mayoría de ellas están desactualizadas ... Todavía estoy luchando, que no hay una configuración o algo incorporado que permita a los usuarios de diferentes países trabajar con aplicaciones MVC.
Modelo:
[DisplayFormat(DataFormatString = "{0:n2}", ApplyFormatInEditMode = true)]
public Double Gewicht
{
get { return gewicht; }
set { gewicht = value; OnPropertyChanged(new PropertyChangedEventArgs("Gewicht")); }
}
CSHTML:
<div class="form-group">
@Html.LabelFor(model => model.Gewicht, htmlAttributes: new { @class = "control-label col-md-3" })
<div class="col-md-8">
@Html.EditorFor(model => model.Gewicht, new { htmlAttributes = new { @class = "form-control col-md-1" } })
@Html.ValidationMessageFor(model => model.Gewicht, "", new { @class = "text-danger" })
</div>
</div>
Web.config
<globalization uiCulture="de-DE" culture="de-DE" />
Cuadro después de su carga -> Valor cargado con una coma como separador decimal
Haga clic en el cuadro después de enviar -> Error de validación para el mismo valor
El cuadro después de la coma se cambia al punto -> Sin error de validación
Actualización 05.01.2018
He probado la solución que se muestra here que desafortunadamente no funciona para mí. Sin embargo, también descubrí que los valores no solo no son aceptados, sino que también se cambian a números donde el separador de grupos y el separador decimal se mezclan (ver imagen). Lo que sucede es que el valor de 22 se cambia a 22.5 y se almacena en la base de datos. El resultado es que se almacena un valor de 2,250.00 en la base de datos.
Actualización 07.01.2018
Lo que también es interesante es el hecho de que los campos de fecha aceptan el formato alemán perfectamente bien.
Propiedad
private DateTime? inbetriebnahmedatum;
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime? Inbetriebnahmedatum
{
get { return inbetriebnahmedatum; }
set { inbetriebnahmedatum = value; OnPropertyChanged(new PropertyChangedEventArgs("Inbetriebnahmedatum")); }
}
El valor que se muestra a continuación se acepta y procesa sin ningún error.
Actualización 07.01.2018 - 2
Si cambio la línea en edit.cshtml de
<input asp-for="Gewicht" class="form-control" />
a
<input name="Gewicht" id="Gewicht" type="number" class="form-control" value="@Model.Gewicht"/>
El formulario se puede enviar con el valor "23,7" sin errores de validación.
En el controlador, la propiedad del modelo enlazado muestra un valor de "237", mientras que
IFormCollection
muestra un valor de "23.7".
Esto sugeriría un problema con el modelo de carpeta.
Aunque se sugirió que este es más un problema de jQuery que un problema de MVC, creo que es un problema de MVC.
No, eso no es correcto.
Usted ve un error de validación del lado del cliente porque, de forma predeterminada,
jquery.validate.js
(un complemento de terceros independiente no asociado con MicroSoft, que MVC usa para la validación del lado del cliente) valida los números en función del separador decimal como a
.
(punto), no un
,
(coma).
MVC es un código del lado del servidor y no se ejecuta en el navegador.
Para realizar la validación del lado del cliente, los métodos
HtmlHelper
de MVC que generan controles de formulario representan un conjunto de atributos
data-val-*
en el html utilizado para describir la validación a realizar, que a su vez son analizados por el complemento
jquery.validate.unobtrusive.js
cuando se carga el DOM, y los usa para agregar reglas al
$.validator
.
En el caso de su propiedad
double
, agregará un atributo
data-val-number
(además del atributo
data-val-required
), que agregará la regla de
number
que se define como
// http://docs.jquery.com/Plugins/Validation/Methods/number
number: function( value, element ) {
return this.optional(element) || /^-?(?:/d+|/d{1,3}(?:,/d{3})+)?(?:/./d+)?$/.test(value);
},
donde el separador decimal es un punto y el separador de miles es una coma (presumiblemente porque el complemento se desarrolló en los EE. UU., por lo que utiliza un formato estadounidense).
jquery.globalize sobrescribir el comportamiento predeterminado que puede hacer mediante el uso de complementos como jquery.globalize o incluir el siguiente script (tenga en cuenta que la expresión regular simplemente intercambia el punto y la coma)
$.validator.methods.number = function (value, element) {
return this.optional(element) || /^-?(?:/d+|/d{1,3}(?:/./d{3})+)?(?:,/d+)?$/.test(value);
}
Tenga en cuenta que la secuencia de comandos anterior debe ser posterior a la
jquery.validate.js
comandos
jquery.validate.js
pero no debe
jquery.validate.js
en
$(document).ready()
Lo que lo vincula a MVC para mí es el hecho de que puedo resolver el problema de validación de fecha agregando la línea
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
al modelo.
En realidad, es su atributo
[DataType(DataType.Date)]
junto con el atributo
[DisplayFormat]
que influye en el html que se genera.
El atributo
[DataType]
genera
<input type="date" ... />
que a su vez representa el selector de fecha HTML-5 de los navegadores si el navegador lo admite.
De acuerdo con las especificaciones, el formato debe ser
yyyy-MM-dd
(formato ISO), de ahí la necesidad del atributo
[DisplayFormat]
también.
El selector de fecha HTML-5 representa la fecha en la cultura de los navegadores.
La imagen que ha mostrado donde la entrada es
26.1.2018
se debe a que la cultura de su navegador es
de-DE
, pero si navegara a su sitio, vería
26/1/2018
en la entrada porque mi cultura es
en-AU
(Australiana ), y si un usuario de los Estados Unidos navegara a su sitio, vería
1/26/2018
.
La razón por la que la validación del lado del cliente funciona para la propiedad de fecha es que el complemento
jquery.validate.js
incluye reglas de fecha para el formato de EE. UU. (
MM/dd/yyyy
) y el formato ISO (
yyyy-MM-dd
).
Y si usara
@Html.TextBoxFor(m => m.Inbetriebnahmedatum)
(que ignora sus atributos
[DataType]
y
[DisplayFormat]
), e ingresó
26.1.2018
en la entrada, también vería un error de validación del lado del cliente .
Creo que el problema es el validador jquery que utilicé para resolver el error de coma / punto
$.validator.methods.number = function (value, element) {
return this.optional(element) || /^-?(?:/d+|/d{1,3}(?:[/s/.,]/d{3})+)(?:[/.,]/d+)?$/.test(value);
}
solo intenta jugar con eso
Una solución más sólida podría ser envolver los métodos de validación en su propia función que convierte su número separado por comas en uno separado por decimales.
Un truco es usar .call para llamar a la función de validación original como si "this" fuera el original this que los desarrolladores pensaron (por ejemplo, usan una función "this.optional" para su validación de pasos).
var originalNumber = $.validator.methods.number;
var wrappedNumber = function (value, element) {
var fixedValue = parseFloat(value.toString().replace(",", "."));
return originalNumber.call($.validator.prototype, fixedValue, element); // Call function as if "this" is the original caller
};
$.validator.methods.number = wrappedNumber;
Puede hacer que esto funcione para cualquier validador, por ejemplo, la validación de pasos:
var originalStep = $.validator.methods.step;
var wrappedStep = function (value, element, param) {
var fixedValue = parseFloat(value.toString().replace(",", "."));
return originalStep.call($.validator.prototype, fixedValue, element, param);
};
$.validator.methods.step = wrappedStep;