14

Mis formularios tienen entradas con texto de ayuda predeterminado que guía al usuario sobre qué debe ingresar (en lugar de usar etiquetas). Esto dificulta la validación porque el valor de entrada nunca es nulo.mvc3 validate input 'not-equal-to'

¿Cómo puedo extender la validación discreta para manejar esto? El formulario no debería ser válido si la entrada de Nombre es igual a "Por favor, introduzca su nombre ..."

Comencé a leer Brad Wilson's blog post en adaptadores de validación, pero no estoy seguro de si este es el camino correcto a seguir. Necesito poder validar contra diferentes valores predeterminados dependiendo del campo.

Gracias

+0

Como alternativa, puede utilizar el [atributo marcador de posición] (https: // desarrollador .mozilla.org/es-US/docs/Web/HTML/Element/input # attr-placeholder) para mostrar texto de instrucciones como "Por favor ingrese su nombre ..." como un UX mucho más amigable y también forma compatible con estándares HTML5 para proporcionar una pista al usuario. – KyleMit

Respuesta

2

Si ése es el camino correcto a seguir. Debe implementar su propio atributo e implementar IClientValidatable.

También podría tener un valor booleano requerido establecido inicialmente en false como un campo de formulario oculto. Cuando el usuario cambia el cuadro de texto, establézcalo en verdadero.

-1

Las soluciones ideales es un atributo personalizado en el que se especifican las longitudes mínima y máxima, así como MustNotContain = "Introduzca su nombre ...".

+0

Realmente no veo cómo esta respuesta tiene algo que ver con lo que se pregunta aquí, que es cómo validar que las dos propiedades en el modelo de vista no son iguales. –

+1

Leí la pregunta como: ¿Cómo sé que el campo Nombre contiene un nombre válido y no el valor predeterminado de "Ingrese su nombre". La validación de esta naturaleza se puede realizar con un atributo muy genérico que se puede usar en muchos campos. – Leons

0

Puede hacer que su ViewModel implemente IValidatableObject y cuando implemente el método Validate (desde IValidatableObject) agregue un poco de lógica para verificar los valores de las propiedades, p.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { 
     var results = new List<ValidationResult>(); 

     if (Name == "Please enter your name...") 
      results.Add(new ValidationResult("You must enter a name"); 

     ... 
     Enter other validation here 
     ...  

     return results; 
    } 

Ahora, cuando Model.IsValid se llama en su controlador, este poco de lógica se corrió y se volverá errores de validación de forma normal.

31

He aquí una muestra que ilustra cómo se puede proceder a aplicar un atributo de validación personalizada:

public class NotEqualAttribute : ValidationAttribute, IClientValidatable 
{ 
    public string OtherProperty { get; private set; } 
    public NotEqualAttribute(string otherProperty) 
    { 
     OtherProperty = otherProperty; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var property = validationContext.ObjectType.GetProperty(OtherProperty); 
     if (property == null) 
     { 
      return new ValidationResult(
       string.Format(
        CultureInfo.CurrentCulture, 
        "{0} is unknown property", 
        OtherProperty 
       ) 
      ); 
     } 
     var otherValue = property.GetValue(validationContext.ObjectInstance, null); 
     if (object.Equals(value, otherValue)) 
     { 
      return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
     } 
     return null; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ErrorMessage = ErrorMessage, 
      ValidationType = "notequalto", 
     }; 
     rule.ValidationParameters["other"] = OtherProperty; 
     yield return rule; 
    } 
} 

y luego en el modelo:

public class MyViewModel 
{ 
    public string Prop1 { get; set; } 

    [NotEqual("Prop1", ErrorMessage = "should be different than Prop1")] 
    public string Prop2 { get; set; } 
} 

controlador:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel 
     { 
      Prop1 = "foo", 
      Prop2 = "foo" 
     }); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     return View(model); 
    } 
} 

y la vista :

@model MyViewModel 

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 
<script type="text/javascript"> 
    jQuery.validator.unobtrusive.adapters.add(
     'notequalto', ['other'], function (options) { 
      options.rules['notEqualTo'] = '#' + options.params.other; 
      if (options.message) { 
       options.messages['notEqualTo'] = options.message; 
      } 
    }); 

    jQuery.validator.addMethod('notEqualTo', function(value, element, param) { 
     return this.optional(element) || value != $(param).val(); 
    }, ''); 
</script> 

@using (Html.BeginForm()) 
{ 
    <div> 
     @Html.LabelFor(x => x.Prop1) 
     @Html.EditorFor(x => x.Prop1) 
     @Html.ValidationMessageFor(x => x.Prop1) 
    </div> 
    <div> 
     @Html.LabelFor(x => x.Prop2) 
     @Html.EditorFor(x => x.Prop2) 
     @Html.ValidationMessageFor(x => x.Prop2) 
    </div> 
    <input type="submit" value="OK" /> 
} 
+1

Muy buena respuesta +1 – tgriffiths

+0

Funciona como un encanto, pero la solución que proporcionó no puede usar ErrorMessageResourceType y ErrorMessageResourceName. Podría usar algo como: errorMessage = new ResourceManager (ErrorMessageResourceType) .GetString (ErrorMessageResourceName); – Rookian

+0

Excelente respuesta, muy útil para ponerme en el camino correcto para hacer algunos validadores personalizados. – Etch

0

tomó un poco de tiempo desde que se le pidió a su pregunta, pero si aún así como anotaciones de datos, este problema puede ser resuelto fácilmente usando this library:

[Required] 
[AssertThat("FieldA != 'some text'")] 
public string FieldA { get; set; } 

Por encima, el valor del campo se compara con un poco de pre texto definido Alternativamente, puede comparar valores de campos entre sí:

[AssertThat("FieldA != FieldB")] 

...y cuando el caso de las cadenas que se comparan no importa:

[AssertThat("CompareOrdinalIgnoreCase(FieldA, FieldB) != 0")] 
0

Para mejorar un poco de respuesta @Darin Dimitrov, si desea agregar mensajes de los recursos que utilizan ErrorMessageResourceName and ErrorMessageResourceType, sólo tiene que añadir esto a la de la mensaje de error ErrorMessage = ErrorMessage ?? ErrorMessageString

el ErrorMessageString buscará la versión localizada del mensaje de error que se establece en el modelo de uso de estos parámetros (ErrorMessageResourceName y ErrorMessageResourceType)

Cuestiones relacionadas