jquery - validate - mvc 5 ajax form validation unobtrusive
La validaciĆ³n MVC 4 del lado del cliente no funciona (19)
¿Puede alguien decirme por qué la validación del lado del cliente no funciona en mi aplicación MVC 4?
_layout.schtml
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
En mi web.config tengo:
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
En mi página login.cshtml tengo:
@using (Html.BeginForm())
{
<div class="formscontent">
<ol>
<li>
@Html.LabelFor(x => x.AgreementNumber)
<br />
@Html.TextBoxFor(x => x.AgreementNumber, new { size = "30" })
<br />
@Html.ValidationMessageFor(m => m.AgreementNumber)
<br />
<br />
</li>
<li>
@Html.LabelFor(x => x.UserName)
<br />
@Html.TextBoxFor(x => x.UserName, new { size = "30" })
<br />
@Html.ValidationMessageFor(m => m.UserName)
<br />
<br />
</li>
<li>
@Html.LabelFor(x => x.Password)
<br />
@Html.PasswordFor(x => x.Password, new { size = "30" })
<br />
@Html.ValidationMessageFor(m => m.Password)
<br />
<br />
</li>
</ol>
</div>
<ol>
<li>
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe, new { @class = "checkbox" })
</li>
</ol>
<br />
<input class="mainbutton" type="submit" value="@Model.Localisation.TranslateHtmlString("LogonBtn")" /><br />
<div style="text-align: left; padding: 0 5px 5px 10px;">
Forgot login-info? clik <a class="link" href="@Url.Action("Index", "Credentials")">here.</a>
</div>
}
En la parte inferior de la página de inicio de sesión:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
JavaScript está habilitado en mi navegador. En el proyecto de plantilla MVC 4 de la validación del cliente de Visual Studio funciona bien.
Al ejecutar la aplicación, en la página de inicio de sesión cuando veo el origen de la página, veo esto procesado:
<label for="AgreementNumber">number</label>
<br />
<input id="AgreementNumber" name="AgreementNumber" size="30" type="text" value="387893" />
<br />
<span class="field-validation-valid" data-valmsg-for="AgreementNumber" data-valmsg- replace="true"></span>
y en esto en la parte inferior:
<script src="/BMWebsite/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/BMWebsite/Scripts/jquery.validate.inline.js"></script>
<script src="/BMWebsite/Scripts/jquery.validate.js"></script>
<script src="/BMWebsite/Scripts/jquery.validate.unobtrusive.js"></script>
Las propiedades de mi modelo están anotadas:
public class LogonModel : ModelBase
{
[MyRequired("AgreementNumberRequiredProperty")]
[MyDisplay("AgreementNumberLabel")]
public string AgreementNumber { get; set; }
[MyRequired("UserNameRequiredProperty")]
[MyDisplay("UserNameLabel")]
public string UserName { get; set; }
[MyRequired("PasswordRequiredProperty")]
[DataType(DataType.Password)]
[MyDisplay("PasswordLabel")]
public string Password { get; set; }
[MyDisplay("RememberMeCheckBox")]
public bool RememberMe { get; set; }
}
MyRequired
es una clase derivada del RequiredAttribute regular. El motivo es que mis mensajes de error se localizan anulando el FormatErrorMessage(string name)
de la clase RequiredAttribute
. Y funciona bien: mis etiquetas y mensajes de error están localizados.
MyRequired.cs
public class MyRequiredAttribute : RequiredAttribute
{
private readonly string _errorMessagekey;
public MyRequiredAttribute(string errorMessage)
{
_errorMessagekey = errorMessage;
}
public override string FormatErrorMessage(string name)
{
var translation = HttpContext.Current.Session["translation"] as LocalisationHelper;
return translation != null ? translation.Translate(_errorMessagekey) : ErrorMessage;
}
}
Puse un punto de interrupción en la versión POST de mi método de acción de inicio de sesión, y está siendo golpeado. El formulario se publica en el servidor donde ocurre la validación del lado del servidor. La validación del lado del cliente no ocurre.
¿Qué me estoy perdiendo?
Gracias.
Asegúrese de agregar este comando al final de cada vista donde desee que las validaciones estén activas.
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
El motivo por el que los atributos de validación data * no se muestran en el html representado para su entrada podría ser que no hay contexto de formulario. FormContext se crea automáticamente cuando crea un formulario usando @using(Html.BeginForm(...)) { ... }
.
Si usa una etiqueta html regular para su formulario, no obtendrá la validación del lado del cliente.
En el método Global.asax.cs, Application_Start (), agregue:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(MyRequiredAttribute), typeof(RequiredAttributeAdapter));
En mi caso, agregué y el id es igual al nombre generado automáticamente para VS en el html y en el código he agregado una línea para ese caso.
$(function () {
$.validator.addMethod(''latinos'', function (value, element) {
return this.optional(element) || /^[a-záéóóúàèìòùäëïöüñ/s]+$/i.test(value);
});
$("#btn").on("click", function () {
//alert("aa");
$("#formulario").validate({
rules:
{
email: { required: true, email: true, minlength: 8, maxlength: 80 },
digitos: { required: true, digits: true, minlength: 2, maxlength: 100 },
nombres: { required: true, latinos: true, minlength: 3, maxlength: 50 },
NombresUsuario: { required: true, latinos: true, minlength: 3, maxlength: 50 }
},
messages:
{
email: {
required: ''El campo es requerido'', email: ''El formato de email es incorrecto'',
minlength: ''El mínimo permitido es 8 caracteres'', maxlength: ''El máximo permitido son 80 caracteres''
},
digitos: {
required: ''El campo es requerido'', digits: ''Sólo se aceptan dígitos'',
minlength: ''El mínimo permitido es 2 caracteres'', maxlength: ''El máximo permitido son 10 caracteres''
},
nombres: {
required: ''El campo es requerido'', latinos: ''Sólo se aceptan letras'',
minlength: ''El mínimo permitido es 3 caracteres'', maxlength: ''El máximo permitido son 50 caracteres''
},
NombresUsuario: {
required: ''El campo es requerido'', latinos: ''Sólo se aceptan letras'',
minlength: ''El mínimo permitido es 3 caracteres'', maxlength: ''El máximo permitido son 50 caracteres''
}
}
});
});
<tr>@*<div class="form-group"> htmlAttributes: new { @class = "control-label col-md-2" } , @class = "form-control" }*@
<td>@Html.LabelFor(model => model.NombresUsuario )</td>
@*<div class="col-md-10">*@
<td>
@Html.EditorFor(model => model.NombresUsuario, new { htmlAttributes = new { id = "NombresUsuario" } })
@Html.ValidationMessageFor(model => model.NombresUsuario, "", new { @class = "text-danger" })
</td>
En mi caso, la validación en sí estaba funcionando (podía validar un elemento y recuperar un valor booleano correcto), pero no había salida visual.
Mi error fue que olvidé esta línea @ Html.ValidationMessageFor (m => ...)
El TS tiene esto en su código y me puso en el camino correcto, pero lo puse aquí como referencia para los demás.
Finalmente resolví este problema al incluir los scripts necesarios directamente en mi archivo .cshtml, en este orden:
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
Está un poco fuera de tema, pero estoy continuamente sorprendido por la frecuencia con que sucede este tipo de cosas en la programación web, es decir, todo parece estar en su lugar, pero se necesita un tweak oscuro para que las cosas funcionen. Endeble, endeble, frágil.
La siguiente línea muestra que no ha configurado un DataAttribute como se requiere en AgreementNumber
<input id="AgreementNumber" name="AgreementNumber" size="30" type="text" value="387893" />
necesitas
[Required]
public String AgreementNumber{get;set;}
Me gustaría agregar a esta publicación que estaba experimentando el mismo problema pero en una vista parcial.
Y necesitaba agregar
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
A la vista parcial, incluso si ya está presente en la vista _Layout.
Referencias
Mi problema estaba en web.config: UnobtrusiveJavaScriptEnabled estaba desactivado
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
</appSettings>
Cambié a y ahora funciona:
`<add key="UnobtrusiveJavaScriptEnabled" value="true" />`
No hay atributos de validación de datos en su entrada. Asegúrese de haberlo generado con un ayudante del lado del servidor como Html.TextBoxFor y que está dentro de un formulario:
@using (Html.BeginForm())
{
...
@Html.TextBoxFor(x => x.AgreementNumber)
}
Además, no sé qué es el script jquery.validate.inline.js
pero si de alguna manera depende del complemento jquery.validate.js
asegúrese de que se haga referencia a él después.
En todos los casos, busque en la consola de JavaScript del navegador los posibles errores o las secuencias de comandos que faltan.
Para mí esto fue mucha búsqueda. Finalmente, decidí usar NuGet en lugar de descargar los archivos yo mismo. Eliminé todos los scripts y scripts involucrados y obtuve los siguientes paquetes (últimas versiones a partir de ahora)
- jQuery (3.1.1)
- Validación jQuery (1.15.1)
- Microsoft jQuery Ubobtrusive Ajax (3.2.3)
- Validación discreta de Microsoft jQuery (3.2.3)
Luego agregué estos paquetes al archivo BundleConfig:
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js"));
Agregué esta referencia a _Layout.cshtml:
@Scripts.Render("~/bundles/jquery")
Y agregué esta referencia a cualquier vista que necesite validación:
@Scripts.Render("~/bundles/jqueryval")
Ahora todo funcionó.
No olvide estas cosas (muchas personas las olvidan):
- Etiquetas de formulario (@using (Html.BeginForm ()))
- Resumen de validación (@ Html.ValidationSummary ())
- Mensaje de validación en su entrada (Ejemplo: @ Html.ValidationMessageFor (model => model.StartDate))
- Configuración ()
- El orden de los archivos agregados al paquete (como se indicó anteriormente)
Si usa jquery.validate.js
y jquery.validate.unobtrusive.js
para validar en el lado del cliente, debe recordar que debe registrar cualquier atributo de validación de cualquier elemento DOM en su solicitud. Por lo tanto, puede usar este código:
$.validator.unobtrusive.parse(''your main element on layout'');
para registrar todos los atributos de validación Puede invocar este método (por ejemplo): $(document).ajaxSuccess() or $(document).ready()
para registrarlos todos y su validación puede realizarse con éxito en lugar de registrar todos los archivos js en archivos cshtml.
Tuve un problema con la validación, las publicaciones del formulario validan,
Esto no funciona con jquery cdn
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Esto funciona sin jquery cdn
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
Hope ayuda a alguien
Utilizar:
@ Html.EditorFor
En lugar de:
@ Html.TextBoxFor
Yo tuve el mismo problema. Parece que los scripts de validación no intrusivos no se cargaron (ver captura de pantalla al final). Lo arreglé añadiendo al final de _Layout.cshtml
@Scripts.Render("~/bundles/jqueryval")
El final resulto:
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@RenderSection("scripts", required: false)
Excepto por mis bonitas vistas CRUD estándar, todo es por defecto la plantilla del proyecto Visual Studio.
Scripts cargados después de solucionar el problema:
es posible que ya hayas resuelto esto, pero tuve un poco de suerte al cambiar el orden del elemento jqueryval en BundleConfig con App_Start. La validación del lado del cliente no funcionaría incluso en una nueva solución de Internet MVC 4 lista para usar. Así que cambié el valor predeterminado:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
a
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*",
"~/Scripts/jquery.unobtrusive*"));
y ahora mi validación del lado del cliente está funcionando. Solo quiere asegurarse de que el archivo discreto esté al final (para que no sea intrusivo, ja, ja :)
<form action="/StudentInfo/Edit/2" method="post" novalidate="novalidate">
este html <form action="/StudentInfo/Edit/2" method="post" novalidate="novalidate">
donde el novalidate="novalidate"
impedía que el jQuery del lado del cliente se ejecutara, cuando novalidate="novalidate"
, jQuery del lado del cliente estaba habilitado y se veía funcionando.
@section Scripts
{
<script src="../Scripts/jquery.validate-vsdoc.js"></script>
<script src="../Scripts/jquery.validate.js"></script>
<script src="../Scripts/jquery.validate.min.js"></script>
<script src="../Scripts/jquery.validate.unobtrusive.js"></script>
<script src="../Scripts/jquery.validate.unobtrusive.min.js"></script>
}
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
Este código funcionó para mí.