2010-09-14 33 views
23

En un modelo de mi aplicación ASP.NET MVC, me gustaría validar un cuadro de texto como se requiere solo si se marca una casilla de verificación específica.atributo dependiente de otro campo

Algo así como

public bool retired {get, set}; 

[RequiredIf("retired",true)] 
public string retirementAge {get, set}; 

¿Cómo puedo hacer eso?

Gracias.

+1

'[RequiredIf ("retiró == true")]' [más aquí] (https://github.com/JaroslawWaliszko/ExpressiveAnnotations) – jwaliszko

Respuesta

3

No he visto nada de fábrica que te permita hacer esto.

He creado una clase para que uses, es un poco áspera y definitivamente no es flexible ... pero creo que puede resolver tu problema actual. O al menos te pone en el camino correcto.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.ComponentModel.DataAnnotations; 
using System.Globalization; 

namespace System.ComponentModel.DataAnnotations 
{ 
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 
    public sealed class RequiredIfAttribute : ValidationAttribute 
    { 
     private const string _defaultErrorMessage = "'{0}' is required"; 
     private readonly object _typeId = new object(); 

     private string _requiredProperty; 
     private string _targetProperty; 
     private bool _targetPropertyCondition; 

     public RequiredIfAttribute(string requiredProperty, string targetProperty, bool targetPropertyCondition) 
      : base(_defaultErrorMessage) 
     { 
      this._requiredProperty   = requiredProperty; 
      this._targetProperty   = targetProperty; 
      this._targetPropertyCondition = targetPropertyCondition; 
     } 

     public override object TypeId 
     { 
      get 
      { 
       return _typeId; 
      } 
     } 

     public override string FormatErrorMessage(string name) 
     { 
      return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, _requiredProperty, _targetProperty, _targetPropertyCondition); 
     } 

     public override bool IsValid(object value) 
     { 
      bool result    = false; 
      bool propertyRequired = false; // Flag to check if the required property is required. 

      PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); 
      string requiredPropertyValue   = (string) properties.Find(_requiredProperty, true).GetValue(value); 
      bool targetPropertyValue    = (bool) properties.Find(_targetProperty, true).GetValue(value); 

      if (targetPropertyValue == _targetPropertyCondition) 
      { 
       propertyRequired = true; 
      } 

      if (propertyRequired) 
      { 
       //check the required property value is not null 
       if (requiredPropertyValue != null) 
       { 
        result = true; 
       } 
      } 
      else 
      { 
       //property is not required 
       result = true; 
      } 

      return result; 
     } 
    } 
} 

Por encima de la clase del modelo, se debe sólo tiene que añadir:

[RequiredIf("retirementAge", "retired", true)] 
public class MyModel 

En su opinión

<%= Html.ValidationSummary() %> 

debe mostrar el mensaje de error cada vez que la propiedad se retiró es verdadero y lo requiere la propiedad esta vacia

Espero que esto ayude.

14

Tome un vistazo a esto: http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx

He modded el código un poco para satisfacer mis necesidades. Quizás también te beneficies de esos cambios.

public class RequiredIfAttribute : ValidationAttribute 
{ 
    private RequiredAttribute innerAttribute = new RequiredAttribute(); 
    public string DependentUpon { get; set; } 
    public object Value { get; set; } 

    public RequiredIfAttribute(string dependentUpon, object value) 
    { 
     this.DependentUpon = dependentUpon; 
     this.Value = value; 
    } 

    public RequiredIfAttribute(string dependentUpon) 
    { 
     this.DependentUpon = dependentUpon; 
     this.Value = null; 
    } 

    public override bool IsValid(object value) 
    { 
     return innerAttribute.IsValid(value); 
    } 
} 

public class RequiredIfValidator : DataAnnotationsModelValidator<RequiredIfAttribute> 
{ 
    public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute) 
     : base(metadata, context, attribute) 
    { } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
    { 
     // no client validation - I might well blog about this soon! 
     return base.GetClientValidationRules(); 
    } 

    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     // get a reference to the property this validation depends upon 
     var field = Metadata.ContainerType.GetProperty(Attribute.DependentUpon); 

     if (field != null) 
     { 
      // get the value of the dependent property 
      var value = field.GetValue(container, null); 

      // compare the value against the target value 
      if ((value != null && Attribute.Value == null) || (value != null && value.Equals(Attribute.Value))) 
      { 
       // match => means we should try validating this field 
       if (!Attribute.IsValid(Metadata.Model)) 
        // validation failed - return an error 
        yield return new ModelValidationResult { Message = ErrorMessage }; 
      } 
     } 
    } 
} 

luego usarlo:

public DateTime? DeptDateTime { get; set; } 
[RequiredIf("DeptDateTime")] 
public string DeptAirline { get; set; } 
+3

es necesario agregar 'DataAnnotationsModelValidatorProvider.RegisterAdapter ( typeof (RequiredIfAttribute) , typeof (RequiredIfValidator)); ' a su global.asax.cs para hacer que esto funcione. (como se describe en el enlace provisto por RickardN. – tkerwood

+0

'ModelMetadata.FromLambdaExpression (ex, html.ViewData) .IsRequired' siempre devuelve' false' aunque el dependiente de la propiedad sea verdadero/falso – Hanady

1

intentar mi costumbre validation attribute:

[ConditionalRequired("retired==true")] 
public string retirementAge {get, set}; 

Es compatible con múltiples condiciones.

+0

Sería bueno si pudieras proporcionar un completo proyecto en su repositorio, que incluye todas las referencias requeridas, como System.Linq.Dynamic. Además, parece que está utilizando una versión personalizada de System.Linq.Dynamic, ya que Microsoft tiene un método 'ExpressionParser.Parse()' que tarda 1 argumento, pero está llamando a una versión de 2 argumentos. –

+0

Gracias @IanKemp, consideraré sus sugerencias y mejoraré el repositorio – karaxuna

+0

@karaxuna ¿Qué hago con ExpressionParser hay un error que me muestra en eso? –

9

sólo tiene que utilizar la biblioteca de validación a toda prueba que está disponible en CodePlex: https://foolproof.codeplex.com/

Es compatible con, entre otros, los siguientes atributos de validación "requiredif"/decoraciones:

[RequiredIf] 
[RequiredIfNot] 
[RequiredIfTrue] 
[RequiredIfFalse] 
[RequiredIfEmpty] 
[RequiredIfNotEmpty] 
[RequiredIfRegExMatch] 
[RequiredIfNotRegExMatch] 

Para empezar es fácil :

  1. Descargar el paquete desde el enlace proporcionado
  2. Añadir una referencia al archivo .dll incluidos
  3. Importe los archivos javascript incluidos
  4. Asegúrese de que sus puntos de vista hace referencia a los archivos javascript incluidos dentro de su discreta HTML para la validación javascript y jQuery.
+0

La prueba completa no funciona con EF 4+. –

+0

Enlace? Parece estar funcionando bien para mí, estoy usando EF 6. Descargué el código fuente de Foolproof y lo compilé yo mismo, ¿quizás eso explica por qué me funciona? –

+0

http://foolproof.codeplex.com/workitem/15609 y http://forums.asp.net/t/1752975.aspx –

1

Con el Administrador de NuGet Paquete I intstalled esto: https://github.com/jwaliszko/ExpressiveAnnotations

Y esta es mi modelo:

using ExpressiveAnnotations.Attributes; 

public bool HasReferenceToNotIncludedFile { get; set; } 

[RequiredIf("HasReferenceToNotIncludedFile == true", ErrorMessage = "RelevantAuditOpinionNumbers are required.")] 
public string RelevantAuditOpinionNumbers { get; set; } 

te garantizo que esto va a funcionar!

Cuestiones relacionadas