requiredif mvc dataannotations data custom attribute annotation c# data-annotations requiredfieldvalidator required
thisthis

c# - mvc - Propiedad condicionalmente requerida usando anotaciones de datos



required if attribute mvc 5 (6)

Tengo una clase como esta:

public class Document { public int DocumentType{get;set;} [Required] public string Name{get;set;} [Required] public string Name2{get;set;} }

Ahora si pongo una anotación de datos [Required] en las propiedades Name y Name2 , entonces todo está bien y si Name o Name2 están vacíos, la validación generará un error.

Pero quiero que el campo Name solo sea obligatorio si DocumentType es igual a 1 y Name2 solo es necesario si DocumentType es igual a 2.

public class Document { public int DocumentType{get;set;} [Required(Expression<Func<object, bool>>)] public string Name{get;set;} [Required(Expression<Func<object, bool>>)] public string Name2{get;set;} }

pero sé que no puedo, causa un error. ¿Qué debo hacer para este requisito?


ObligatorioSi el atributo de validación

He escrito un RequiredIfAttribute que requiere un valor de propiedad particular cuando una propiedad diferente tiene un cierto valor (lo que necesita) o cuando una propiedad diferente tiene algo más que un valor específico.

Este es el código que puede ayudar:

/// <summary> /// Provides conditional validation based on related property value. /// </summary> [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public sealed class RequiredIfAttribute : ValidationAttribute { #region Properties /// <summary> /// Gets or sets the other property name that will be used during validation. /// </summary> /// <value> /// The other property name. /// </value> public string OtherProperty { get; private set; } /// <summary> /// Gets or sets the display name of the other property. /// </summary> /// <value> /// The display name of the other property. /// </value> public string OtherPropertyDisplayName { get; set; } /// <summary> /// Gets or sets the other property value that will be relevant for validation. /// </summary> /// <value> /// The other property value. /// </value> public object OtherPropertyValue { get; private set; } /// <summary> /// Gets or sets a value indicating whether other property''s value should match or differ from provided other property''s value (default is <c>false</c>). /// </summary> /// <value> /// <c>true</c> if other property''s value validation should be inverted; otherwise, <c>false</c>. /// </value> /// <remarks> /// How this works /// - true: validated property is required when other property doesn''t equal provided value /// - false: validated property is required when other property matches provided value /// </remarks> public bool IsInverted { get; set; } /// <summary> /// Gets a value that indicates whether the attribute requires validation context. /// </summary> /// <returns><c>true</c> if the attribute requires validation context; otherwise, <c>false</c>.</returns> public override bool RequiresValidationContext { get { return true; } } #endregion #region Constructor /// <summary> /// Initializes a new instance of the <see cref="RequiredIfAttribute"/> class. /// </summary> /// <param name="otherProperty">The other property.</param> /// <param name="otherPropertyValue">The other property value.</param> public RequiredIfAttribute(string otherProperty, object otherPropertyValue) : base("''{0}'' is required because ''{1}'' has a value {3}''{2}''.") { this.OtherProperty = otherProperty; this.OtherPropertyValue = otherPropertyValue; this.IsInverted = false; } #endregion /// <summary> /// Applies formatting to an error message, based on the data field where the error occurred. /// </summary> /// <param name="name">The name to include in the formatted message.</param> /// <returns> /// An instance of the formatted error message. /// </returns> public override string FormatErrorMessage(string name) { return string.Format( CultureInfo.CurrentCulture, base.ErrorMessageString, name, this.OtherPropertyDisplayName ?? this.OtherProperty, this.OtherPropertyValue, this.IsInverted ? "other than " : "of "); } /// <summary> /// Validates the specified value with respect to the current validation attribute. /// </summary> /// <param name="value">The value to validate.</param> /// <param name="validationContext">The context information about the validation operation.</param> /// <returns> /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> class. /// </returns> protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (validationContext == null) { throw new ArgumentNullException("validationContext"); } PropertyInfo otherProperty = validationContext.ObjectType.GetProperty(this.OtherProperty); if (otherProperty == null) { return new ValidationResult( string.Format(CultureInfo.CurrentCulture, "Could not find a property named ''{0}''.", this.OtherProperty)); } object otherValue = otherProperty.GetValue(validationContext.ObjectInstance); // check if this value is actually required and validate it if (!this.IsInverted && object.Equals(otherValue, this.OtherPropertyValue) || this.IsInverted && !object.Equals(otherValue, this.OtherPropertyValue)) { if (value == null) { return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } // additional check for strings so they''re not empty string val = value as string; if (val != null && val.Trim().Length == 0) { return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } } return ValidationResult.Success; } }


Compruebe la validación MVC a prueba de tontos. Tiene una anotación de datos en el modelo como RequiredIf (propiedad dependiente, valor dependiente) si no recuerdo mal. Puede descargar Foolproof desde Herramientas -> Administrador de paquetes Nuget -> Administrar paquetes Nuget para soluciones si usa VS2017. Referencia mvcfoolproof.unobtrusive.min.js además de los archivos jquery.


Fuera de la caja, creo que esto aún no es posible.

Pero encontré este artículo prometedor sobre Mvc.ValidationToolkit (también here , desafortunadamente this es solo alfa, pero probablemente también podrías simplemente extraer el método (s) que necesitas de este código e integrarlo por tu cuenta) , contiene el sonido agradable atributo RequiredIf parece coincidir exactamente con tu causa:

  • usted descarga el proyecto desde el this y lo construye
  • obtener el dll generado de su carpeta de compilación y hacer referencia a él en el proyecto que está utilizando
  • desafortunadamente, esto parece requerir también una referencia a MVC (la forma más fácil de hacerlo es iniciar MVC-Project en VS o install-package Microsoft.AspNet.Mvc )
  • en los archivos donde desee usarlo, agregue using Mvc.ValidationToolkit;
  • luego puede escribir cosas como [RequiredIf("DocumentType", 2)] o [RequiredIf("DocumentType", 1)] , por lo que los objetos son válidos si no se proporcionan ni name ni name2 , siempre que DocumentType no sea igual a 1 o 2

No puedo darte exactamente lo que estás pidiendo, pero ¿has considerado algo como lo siguiente?

public abstract class Document // or interface, whichever is appropriate for you { //some non-validted common properties } public class ValidatedDocument : Document { [Required] public string Name {get;set;} } public class AnotherValidatedDocument : Document { [Required] public string Name {get;set;} //I would suggest finding a descriptive name for this instead of Name2, //Name2 doesn''t make it clear what it''s for public string Name2 {get;set;} } public class NonValidatedDocument : Document { public string Name {get;set;} } //Etc...

La justificación es la variable int DocumentType . Puede reemplazar esto con el uso de tipos de subclases concretos para cada "tipo" de documento con el que deba lidiar. Hacer esto le da un mejor control de sus anotaciones de propiedad.

También parece que solo se necesitan algunas de tus propiedades en diferentes situaciones, lo que podría ser una señal de que tu clase de documento está intentando hacer demasiado y es compatible con la sugerencia anterior.



Propiedad condicionalmente requerida usando anotaciones de datos

[RequiredIf(dependent Property name, dependent Property value)] e.g. [RequiredIf("Country", "Ethiopia")] public string POBox{get;set;} // POBox is required in Ethiopia public string Country{get;set;} [RequiredIf("destination", "US")] public string State{get;set;} // State is required in US public string destination{get;set;} public class RequiredIfAttribute : ValidationAttribute { RequiredAttribute _innerAttribute = new RequiredAttribute(); public string _dependentProperty { get; set; } public object _targetValue { get; set; } public RequiredIfAttribute(string dependentProperty, object targetValue) { this._dependentProperty = dependentProperty; this._targetValue = targetValue; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var field = validationContext.ObjectType.GetProperty(_dependentProperty); if (field != null) { var dependentValue = field.GetValue(validationContext.ObjectInstance, null); if ((dependentValue == null && _targetValue == null) || (dependentValue.Equals(_targetValue))) { if (!_innerAttribute.IsValid(value)) { string name = validationContext.DisplayName; return new ValidationResult(ErrorMessage=name + " Is required."); } } return ValidationResult.Success; } else { return new ValidationResult(FormatErrorMessage(_dependentProperty)); } } }