我正在上下面的课:
public class CustomerNameSearchRequest
{
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}我有以下条件:The LastName property is required IF the FirstName is null OR StreetAddress is null OR City is null OR State is null OR ZipCode is null
我已经查找了堆栈溢出,并且习惯于遵循RequiredIf验证属性。
/// <summary>
/// Provides conditional validation based on related property value.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
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;
}
}但是,如果我要实现以下多个RequiredIf属性:
[RequiredIf(nameof(FirstName), null)]
[RequiredIf(nameof(StreetAddress), null)]
[RequiredIf(nameof(City), null)]
[RequiredIf(nameof(State), null)]
[RequiredIf(nameof(ZipCode), null)]
public string LastName { get; set; }不管如何,它都将强制LastName属性具有一个值。如何在RequiredIf属性中实现OR条件?还有更好的代码可以帮助我实现我的需求吗?
提前谢谢。
发布于 2020-05-10 16:04:01
可以将属性更改为接受具有以下字段和值对的字符串数组:
public class CustomerNameSearchRequest
{
public string FirstName { get; set; }
[RequiredIf(new string[] {
"FirstName, !null",
"StreetAddress, !null",
"City, !null",
"State, !null",
"ZipCode, !null"
})]
public string LastName { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}并以下列方式创建RequiredIf属性:
public class RequiredIfAttribute : ValidationAttribute
{
private const string DefaultErrorMessageFormatString = "The {0} field is required.";
private readonly string[] _dependentProperties;
public RequiredIfAttribute(string[] dependentProperties)
{
_dependentProperties = dependentProperties;
ErrorMessage = DefaultErrorMessageFormatString;
}
private bool IsValueRequired(string checkValue, object currentValue)
{
if (checkValue.Equals("!null", StringComparison.InvariantCultureIgnoreCase))
{
return currentValue != null;
}
return checkValue.Equals(currentValue);
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
object instance = context.ObjectInstance;
Type type = instance.GetType();
bool valueRequired = false;
foreach (string s in _dependentProperties)
{
var fieldValue = s.Split(',').ToList().Select(k => k.Trim()).ToArray();
object propertyValue = type.GetProperty(fieldValue[0]).GetValue(instance, null);
valueRequired = IsValueRequired(fieldValue[1], propertyValue);
}
if (valueRequired)
{
return value != null
? ValidationResult.Success
: new ValidationResult(context.DisplayName + " required. ");
}
return ValidationResult.Success;
}
}2.验证字段是否需要(不)的IsValueRequired方法
private bool IsValueRequired(string checkValue, object currentValue)
{
if (checkValue.Equals("!null", StringComparison.InvariantCultureIgnoreCase))
{
return currentValue != null;
}
return checkValue.Equals(currentValue);
}3. IsValid检查字段为空还是不为空:
protected override ValidationResult IsValid(object value, ValidationContext context)
{
object instance = context.ObjectInstance;
Type type = instance.GetType();
bool valueRequired = false;
foreach (string s in _dependentProperties)
{
var fieldValue = s.Split(',').ToList().Select(k => k.Trim()).ToArray();
object propertyValue = type.GetProperty(fieldValue[0]).GetValue(instance, null);
valueRequired = IsValueRequired(fieldValue[1], propertyValue);
}
if (valueRequired)
{
return value != null
? ValidationResult.Success
: new ValidationResult(context.DisplayName + " required. ");
}
return ValidationResult.Success;
}来源:
https://stackoverflow.com/questions/61714030
复制相似问题