Pregunta ASP.NET MVC: impide el envío de formularios no válidos utilizando la validación discreta de jQuery


Tengo un proyecto ASP.NET que conecta automáticamente la validación del lado del cliente usando jQuery.Validate y el envoltura discreta construido por ASP.NET.

a) Definitivamente tengo las bibliotecas apropiadas: jquery.js, jquery.validate.js, & jquery.validate.unobtrusive.js

b) Y el motor de renderizado MVC está definitivamente encendido (ClientValidationEnabled & UnobtrusiveJavaScriptEnabled en el appSettings sección del web.config)

Aquí hay un ejemplo trivial donde las cosas se rompen:

Modelo:

public class Person
{
    [Required]
    public string Name { get; set; }
}

Controlador:

public ActionResult Edit()
{
    Person p = new Person();
    return View(p);
}

Ver:

@model validation.Models.Person

@using (Html.BeginForm()) {
    @Html.ValidationSummary(false)

    @Html.LabelFor(model => model.Name)
    @Html.EditorFor(model => model.Name)
}

Esto genera el siguiente marcado del lado del cliente:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.1/jquery.validate.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js"></script>
    
<form action="/Person" method="post">
  <div class="validation-summary-valid" data-valmsg-summary="true">
    <ul><li style="display:none"></li></ul>
  </div>
  <label for="Name">Name</label>
  <input data-val="true" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" />
  <input type="submit" value="Save" />
</form>

Cuando se ejecute, realizará la validación del lado del cliente, observando que algunos elementos del formulario no son válidos, pero luego además publicar de nuevo en el servidor.

¿Por qué no se impide la devolución de datos en un formulario con un estado no válido?


5
2017-10-07 13:51


origen


Respuestas:


El problema

Resulta que esto sucede cuando no se incluye una @Html.ValidationMessageFor marcador de posición para un elemento de formulario dado.

Aquí hay una inmersión más profunda en donde ocurre el problema:

Cuando se envía un formulario, jquery.validate.js Llamará a los siguientes métodos:

validate: function( options ) {
  form: function() {
    showErrors: function(errors) {
      defaultShowErrors: function() {
        showLabel: function(element, message) {
          this.settings.errorPlacement(label, $(element) )

Dónde errorPlacement llamará a este método en jquery.validate.unobtrusive.js:

function onError(error, inputElement) { 
   var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
       replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;

Cuando no agregamos un marcador de posición para el mensaje de validación, $(this).find(...) no encontrará nada

Sentido container.attr("data-valmsg-replace") regresará undefined

Esto plantea un problema cuando intentamos llamar. $.parseJSON en un valor indefinido. Si se produce un error (y no se detecta), JavaScript se detendrá en seco y nunca alcanzará la última línea de código en el método original (return false) que impide que se envíe el formulario.

La solución

Actualizar jQuery Validar discreta

Nuevas versiones de jQuery Validar maneja esto mejor y comprueba si hay nulos antes de pasarlos a $.parseJSON

function onError(error, inputElement) {  // 'this' is the form element
    var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
        replaceAttrValue = container.attr("data-valmsg-replace"),
        replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;

Añadir ValidationMessageFor

Para abordar el problema principal, para cada entrada en su formulario, asegúrese de incluir:

@Html.ValidationMessageFor(model => model.Name)

Que representará el siguiente marcado del lado del cliente

<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.1/jquery.validate.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js"></script>
    
<form action="/Person" method="post">
  <div class="validation-summary-valid" data-valmsg-summary="true">
    <ul><li style="display:none"></li></ul>
  </div>
  <label for="Name">Name</label>
  <input data-val="true" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" />
  <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
  <input type="submit" value="Save" />
</form>


6
2017-10-07 13:51