5

Tengo lo siguiente en .NET MVC3 usando viewmodels. Estoy usando Razor y FluentValidation (pero también he probado DataAnnotations con los mismos resultados).Activación de Validación de JQuery discrepante en la lista desplegable cuando no debería

De Vista:

@Html.DropDownListFor(model=>model.L2, Model.RegisteredL2s, "[Select One]") 

desde el controlador:

[HttpGet] 
    [Authorize(Roles = "Supervisor")] 
    public ActionResult Edit(string siteId, bool? isNew) 
    { 
      SiteEditViewModel model = new SiteEditViewModel(); 

        List<SelectListItem> items = RegisteredL2Repository.GetRegisteredL2List() 
                 .Select(x => new SelectListItem() { Text = x.L2, Value = x.L2.Trim() }) 
                 .OrderBy(x => x.Text) 
                 .ToList(); 

        model.RegisteredL2s = items.AsEnumerable(); 

        if(!isNew.HasValue) 
        { 
         model.IsNew = false; 
        } 

        if(isNew.HasValue && (bool)isNew) 
        { 
         model.IsNew = true; 
         return View(model); 
        } 

        if(model.IsNew) 
        { 
         return View(model); 
        } 

        model.ConvertModelToViewModel(SiteRepository.GetSite(siteId)); 

        return View("Edit", model); 
       } 
    } 

De ViewModel:

[DisplayName("Site:")] 
      [TextboxLength(2)] 
      public virtual string SiteId { get; set; } 

      [DisplayName("L2:")] 
      public virtual string L2 { get; set; } 

      [DisplayName("Description:")] 
      [TextboxLength(50)] 
      public virtual string Description { get; set; } 

      public IEnumerable<SelectListItem> RegisteredL2s { get; set; } 

      public bool IsNew { get; set; } 

      public string OverallError { get; set; } 

De mi clase Validador (Fluido):

public SiteEditValidator() 
      { 
       RuleFor(model => model.SiteId) 
        .NotEmpty() 
        .WithMessage("Site is required.") 
        .Length(2) 
        .WithMessage("Site must be 2 characters. Ex: 1C") 
        .Matches(@"^[0-9A-Za-z]{2}$") 
        .WithMessage("Site contains invalid characters. Only letters and numbers."); 

       RuleFor(model => model.L2) 
        .NotEmpty() 
        .WithMessage("L2 is required.") 
        .Length(2) 
        .WithMessage("L2 must be 2 characters. Ex: 30") 
        .Matches(@"^[\d]{2}$") 
        .WithMessage("L2 contains invalid characters. Only numbers are allowed."); 

       RuleFor(model => model.Description) 
        .NotEmpty() 
        .WithMessage("Description is required.") 
        .Length(3, 50) 
        .WithMessage("Description must be at least 3 characters and not more than 50.") 
        .Matches(@"^[\w\,\.\'\-\s]{3,50}$") 
        .WithMessage("Description contains some invalid characters."); 
      } 

Y el HTML generado:

<div class="Edit-Field"> 
       <div class="Edit-Field-Label" style="width: 5em"> 
        <label for="SiteId">Site:</label> 
       </div> 
       <div class="Editor-For"> 
        <input autocomplete="off" data-val="true" data-val-length="Site must be 2 characters. Ex: 1C" data-val-length-max="2" data-val-length-min="2" data-val-regex="Site contains invalid characters. Only letters and numbers." data-val-regex-pattern="^[0-9A-Za-z]{2}$" data-val-required="Site is required." id="SiteId" maxlength="2" name="SiteId" readonly="readonly" style="width: 2.5em; background-color: LightGrey" type="text" value="30" /> 
        <div class="Validation-For"> 
         <span class="field-validation-valid" data-valmsg-for="SiteId" data-valmsg-replace="true"></span> 
        </div> 
       </div> 
      </div> 
      <div class="Edit-Field"> 
       <div class="Edit-Field-Label" style="width: 5em"> 
        <label for="L2">L2:</label> 
       </div> 
       <div class="Editor-For"> 
        <select data-val="true" data-val-length="L2 must be 2 characters. Ex: 30" data-val-length-max="2" data-val-length-min="2" data-val-regex="L2 contains invalid characters. Only numbers are allowed." data-val-regex-pattern="^[\d]{2}$" data-val-required="L2 is required." id="L2" name="L2"><option value="">[Select One]</option> 
<option value="30">30</option> 
<option value="31">31</option> 
<option value="32">32</option> 
</select> 
        <div class="Validation-For"> 
         <span class="field-validation-valid" data-valmsg-for="L2" data-valmsg-replace="true"></span> 
        </div> 
       </div> 
      </div> 
      <div class="Edit-Field"> 
       <div class="Edit-Field-Label" style="width: 5em"> 
        <label for="Description">Description:</label> 
       </div> 
       <div class="Editor-For"> 
        <input autocomplete="off" data-val="true" data-val-length="Description must be at least 3 characters and not more than 50." data-val-length-max="50" data-val-length-min="3" data-val-regex="Description contains some invalid characters." data-val-regex-pattern="^[\w\,\.\&#39;\-\s]{3,50}$" data-val-required="Description is required." id="Description" maxlength="50" name="Description" style="width: 30em" type="text" value="Central Office-Cash Receipts Unit" /> 
        <div class="Validation-For"> 
         <span class="field-validation-valid" data-valmsg-for="Description" data-valmsg-replace="true"></span> 
        </div> 
       </div> 
      </div> 

Ahora el problema:

He el campo L2 se extrae de una IEnumerable predefinido (RegisteredL2s) y que tiene que como lista desplegable (ID = L2, más o menos medio del el html). L2 es obligatorio y debe tener una cierta longitud (2). Mi problema es que incluso cuando un usuario ha elegido algo diferente a [Seleccionar uno] aparece el error de longitud. Si elimino ese error, aparece el error Expresión regular. La validación del servidor en el envío funciona correctamente. ¿Por qué está haciendo esto y cómo lo detengo? ¿O puedo simplemente desactivar el lado del cliente para este campo?

Actualización: Creo que he encontrado un problema con jquery.validate.js ... Me gustaría que alguien para confirmar esto.

Aquí están las líneas originales de código que cambié y que parecen haber solucionado mi problema: esta es la línea 683. La línea 686 es el punto problemático.

getLength: function(value, element) { 
    switch(element.nodeName.toLowerCase()) { 
    case 'select': 

     return $("option:selected", element).length;   case 'input': 
     if(this.checkable(element)) 
     return this.findByName(element.name).filter(':checked').length; 
     } 
    return value.length; 
    }, 

Creo que cuando tiene un valor desplegable requerido con el validador de longitud también presente, genera el error. Cuando ejecuto mi código, la longitud de esta línea devuelve 1, no 2. Si cambio la línea en negrita al return $("option:selected", element).val().length;, funciona correctamente. Cualquier comentario sobre si este es un error adecuado y si mi solución no interferirá con ninguna otra parte de jquery.validation sería útil.

Esto es de jquery.validation 1.8.1 (actualizado desde 1.7 ya que pensaba que mis versiones pueden haber estado desincronizadas) Jquery = 1.6.1.

Actualización 2: No estoy seguro si esto debería ser una respuesta exacta, pero:

Resulta que según la documentación JQuery.Validation para rangelength (que es lo jquery.validation.unobtrusive construcciones para una Longitud de exactamente 2) here Establece que para seleccionar (lista desplegable) es para asegurar que un cierto número de elementos ha sido seleccionado no para verificar la longitud del valor.

Estoy después de verificar la longitud del valor o desactivar la validación en el lado del cliente para este artículo en particular mientras retiene la validación del lado del servidor.

Respuesta

1

No es una respuesta completa (no estoy seguro de cómo lograr lo mismo en DataAnnotations) por lo que no la he marcado como la respuesta aceptada.

Bajo FluentValidation me cambió la siguiente línea por encima de

RuleFor(model => model.L2)      
    .NotEmpty()      
    .WithMessage("L2 is required.")      
    .Length(2)      
    .WithMessage("L2 must be 2 characters. Ex: 30")      
    .Matches(@"^[\d]{2}$")      
    .WithMessage("L2 contains invalid characters. Only numbers are allowed."); 

Para:

RuleFor(model => model.L2) 
       .NotEmpty() 
       .WithMessage("L2 is required.") 
       .Length(2) 
       .When(x => 1==1) 
       .WithMessage("L2 must be 2 characters. Ex: 30") 
       .Matches(@"^[\d]{2}$") 
       .WithMessage("L2 contains invalid characters or is too long. Only numbers are allowed."); 

Esta validación del lado del cliente efectivamente desactivado, pero dejó la serverside intacta. Aparentemente Fluent no genera validación del lado del cliente para artículos con condiciones When. Espero que esto ayude a alguien por ahí.

Cuestiones relacionadas