2012-01-18 20 views
13

Tenía dos campos, como el número de teléfono y el número de teléfono móvil. Algo así como ...Cómo validar un campo relacionado con el valor de otro en ASP .NET MVC 3

[Required] 
    public string Phone { get; set; } 

    [Required] 
    public string Mobile{ get; set; } 

Pero el usuario puede ingresar datos en cualquiera de ellos. Uno es obligatorio. Cómo manejarlos, es decir, cómo desactivar el validador de campo requerido para un campo cuando el usuario ingresa datos en otro campo y viceversa. En ese caso, tengo que manejarlo en javascript y cuáles son los scripts que necesito agregar para esto. ¿Puede alguien por favor ayuda para encontrar la solución ...

Respuesta

38

Una posibilidad es escribir un atributo de validación personalizada:

public class RequiredIfOtherFieldIsNullAttribute : ValidationAttribute, IClientValidatable 
{ 
    private readonly string _otherProperty; 
    public RequiredIfOtherFieldIsNullAttribute(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, 
       "Unknown property {0}", 
       new[] { _otherProperty } 
      )); 
     } 
     var otherPropertyValue = property.GetValue(validationContext.ObjectInstance, null); 

     if (otherPropertyValue == null || otherPropertyValue as string == string.Empty) 
     { 
      if (value == null || value as string == string.Empty) 
      { 
       return new ValidationResult(string.Format(
        CultureInfo.CurrentCulture, 
        FormatErrorMessage(validationContext.DisplayName), 
        new[] { _otherProperty } 
       )); 
      } 
     } 

     return null; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), 
      ValidationType = "requiredif", 
     }; 
     rule.ValidationParameters.Add("other", _otherProperty); 
     yield return rule; 
    } 
} 

la que se aplicaría a una de las propiedades de su modelo de vista:

public class MyViewModel 
{ 
    [RequiredIfOtherFieldIsNull("Mobile")] 
    public string Phone { get; set; } 

    public string Mobile { get; set; } 
} 

entonces usted podría tener un controlador:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel()); 
    } 

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

y, finalmente, una vista en los que se registrará un adaptador para conectar la validación del lado del cliente para esta regla personalizada:

@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(
     'requiredif', ['other'], function (options) { 

      var getModelPrefix = function (fieldName) { 
       return fieldName.substr(0, fieldName.lastIndexOf('.') + 1); 
      } 

      var appendModelPrefix = function (value, prefix) { 
       if (value.indexOf('*.') === 0) { 
        value = value.replace('*.', prefix); 
       } 
       return value; 
      } 

      var prefix = getModelPrefix(options.element.name), 
       other = options.params.other, 
       fullOtherName = appendModelPrefix(other, prefix), 
       element = $(options.form).find(':input[name="' + fullOtherName + '"]')[0]; 

      options.rules['requiredif'] = element; 
      if (options.message) { 
       options.messages['requiredif'] = options.message; 
      } 
     } 
    ); 

    jQuery.validator.addMethod('requiredif', function (value, element, params) { 
     var otherValue = $(params).val(); 
     if (otherValue != null && otherValue != '') { 
      return true; 
     } 
     return value != null && value != ''; 
    }, ''); 
</script> 

@using (Html.BeginForm()) 
{ 
    <div> 
     @Html.LabelFor(x => x.Phone) 
     @Html.EditorFor(x => x.Phone) 
     @Html.ValidationMessageFor(x => x.Phone) 
    </div> 

    <div> 
     @Html.LabelFor(x => x.Mobile) 
     @Html.EditorFor(x => x.Mobile) 
     @Html.ValidationMessageFor(x => x.Mobile) 
    </div> 

    <button type="submit">OK</button> 
} 

Cosas bastante enfermo por algo tan extremadamente fácil como regla de validación que encontramos en nuestra vida cotidiana. No sé qué han pensado los diseñadores de ASP.NET MVC cuando decidieron elegir un enfoque declarativo para la validación en lugar de un imperativo.

De todos modos, es por eso que utilizo FluentValidation.NET en lugar de anotaciones de datos para realizar validaciones en mis modelos. La implementación de tales escenarios simples de validación se implementa de una manera que debería ser: simple.

+1

Después de su recomendación, configuré FluentValidation. El problema que estaba tratando de resolver es el mismo que el de esta pregunta, y el validador When() en FV lo resuelve. El problema que tengo es que no hay una validación del lado del cliente para "When()". No soy demasiado cluey en jquery validation atm, pero ¿hay mucho involucrado en la creación de una validación del cliente para ello? Supongo que sería algo similar a lo que hay en tu respuesta, ¿eh? – jzm

+0

Podría heredar de 'RequiredAttribute' para aprovechar el mensaje de error incorporado. –

8

Sé que esta pregunta no es tan positiva, porque se hizo hace relativamente tiempo, sin embargo, voy a compartir con una idea ligeramente diferente de resolver un problema de este tipo. Decidí implementar un mecanismo que proporciona atributos condicionales para calcular resultados de validación basados ​​en otros valores de propiedades y relaciones entre ellos, que se definen en expresiones lógicas.

Su problema puede ser definido y resuelto automáticamente por el uso de las anotaciones siguientes:

[RequiredIf("Mobile == null", 
    ErrorMessage = "At least email or phone should be provided.")] 
public string Phone{ get; set; } 

[RequiredIf("Phone == null", 
    ErrorMessage = "At least email or phone should be provided.")] 
public string Mobile { get; set; } 

Si siente que sería útil para sus propósitos, más información sobre ExpressiveAnnotations biblioteca can be found here. La validación del lado del cliente también es compatible desde el primer momento.

+1

¡Esta biblioteca es excelente! – Roel

+0

No puedo usar este paquete. ¿¿Cómo utilizar?? Pls. ayuadame. – gdmanandamohon

+0

@lazycoder: ¿Te importaría sugerir qué ayuda necesitas? – jwaliszko

Cuestiones relacionadas