[英]Custom required attribute with C# & Web API and using private access modifier with validation context
我具有以下自定義必填屬性:
public class RequiredIfAttribute : RequiredAttribute
{
private string _DependentProperty;
private object _TargetValue;
public RequiredIfAttribute(string dependentProperty, object targetValue)
{
this._DependentProperty = dependentProperty;
this._TargetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this._DependentProperty);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("{0} needs to be exist in this object.", this._DependentProperty));
}
var dependendValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (dependendValue == null)
{
return new ValidationResult(string.Format("{0} needs to be populated.", this._DependentProperty));
}
if (dependendValue.Equals(this._TargetValue))
{
var x = validationContext.ObjectType.GetProperty("_Mappings");
var objectInstance = (Dictionary<object, string[]>)x.GetValue(validationContext.ObjectInstance, null);
var isRequiredSatisfied = false;
foreach (var kvp in objectInstance)
{
if (kvp.Key.Equals(this._TargetValue))
{
foreach (var field in kvp.Value)
{
var fieldValue = validationContext.ObjectType.GetProperty(field).GetValue(validationContext.ObjectInstance, null);
if (fieldValue != null && field.Equals(validationContext.MemberName))
{
isRequiredSatisfied = true;
break;
}
}
}
}
if (isRequiredSatisfied)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(string.Empty);
}
}
else
{
// Must be ignored
return ValidationResult.Success;
}
}
}
我要實現的目標是,我想根據模型中的屬性有條件地進行驗證。 它還需要足夠通用,才能在多個模型上重復使用。 當指定的屬性具有特定值(我在屬性中指定)時,需要的自定義驗證必須與這些值匹配。 例如在此模型中:
public class PaymentModel
{
public Dictionary<object, string[]> _Mappings
{
get
{
var mappings = new Dictionary<object, string[]>();
mappings.Add(true, new string[] { "StockID" });
mappings.Add(false, new string[] { "Amount" });
return mappings;
}
}
[Required]
public bool IsBooking { get; set; }
[RequiredIfAttribute("IsBooking", false)]
public decimal? Amount { get; set; }
[RequiredIf("IsBooking", true)]
public int? StockID { get; set; }
public PaymentModel()
{
}
}
如果IsBooking
屬性為true
,那么我希望需要StockId
,但是如果它為false
,則應該要求Amount
。
目前,我有解決方案,但是有兩個問題:
_Mappings
屬性具有依賴性。 有誰知道我將如何按照自己的方式去做? _Mappings
使用_Mappings
屬性,是否可以將其用作private
訪問修飾符? 當前,只有_Mappings
是public
,我才能使我的解決方案起作用,因為validationContext.ObjectType.GetProperty("_Mappings")
無法找到private
修飾符。 (如果要在Web API響應中將此模型序列化為JSON,那么理想情況下,我將不希望發送驗證映射。) 您可以將_Mappings
私有。 更改此:
var propertyTestedInfo = validationContext.ObjectType.GetProperty("_Mappings");
至
var propertyTestedInfo = validationContext.ObjectType.GetProperty(
"_Mappings",
BindingFlags.NonPublic | BindingFlags.Instance);
要使用此重載獲取私有屬性。
public PropertyInfo Type.GetProperty(string name, BindingFlags bindingAttr)
另外,如果我從您當前的代碼中正確地找到了您的意圖(並且假設您在當前_Mappings
詞典中的意思是“ StockID”,其中它表示“ ReleasedStockID”),那么您可以完全不用_Mappings
。
public class RequiredIfAttribute : RequiredAttribute
{
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private string _DependentProperty;
private object _TargetValue;
public RequiredIfAttribute(string dependentProperty, object targetValue)
{
this._DependentProperty = dependentProperty;
this._TargetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// Property info for the specified dependent property.
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this._DependentProperty, Flags);
if (propertyTestedInfo == null)
return new ValidationResult(string.Format("{0} needs to be exist in this object.", this._DependentProperty));
// And its value
var dependendValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (dependendValue == null)
return new ValidationResult(string.Format("{0} needs to be populated.", this._DependentProperty));
// If it meets the specified "If" predicate value
if (dependendValue.Equals(this._TargetValue))
{
// Get the property being validated.
var validatedProperty = validationContext.ObjectType.GetProperty(validationContext.MemberName, Flags);
if (validatedProperty != null)
{
// Debug sanity check
AssertHasThisAttribute(validatedProperty);
// Get the property's value.
var validatedPropertyValue = validatedProperty.GetValue(validationContext.ObjectInstance, null);
// And check that is is not null
if (validatedPropertyValue != null)
return ValidationResult.Success;
}
// validation failed.
return new ValidationResult(string.Empty);
}
// Must be ignored
return ValidationResult.Success;
}
// Debug only sanity check.
[Conditional("DEBUG")]
private void AssertHasThisAttribute(PropertyInfo prop)
{
var attr = prop.GetCustomAttributes<RequiredIfAttribute>().FirstOrDefault();
Debug.Assert(attr != null);
Debug.Assert(attr._TargetValue == _TargetValue);
Debug.Assert(attr._DependentProperty == _DependentProperty);
}
}
您不必使用_Mappings屬性,下面的代碼檢查相關的Attribute是否具有與您在屬性中指定的值匹配的值,如果存在匹配項,則檢查要驗證的屬性是否具有值。
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this._DependentProperty);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("{0} needs to be exist in this object.", this._DependentProperty));
}
var dependendValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (dependendValue == null)
{
return new ValidationResult(string.Format("{0} needs to be populated.", this._DependentProperty));
}
if (dependendValue.Equals(this._TargetValue))
{
var fieldValue = validationContext.ObjectType.GetProperty(validationContext.MemberName).GetValue(validationContext.ObjectInstance, null);
if (fieldValue != null)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(string.Format("{0} cannot be null", validationContext.MemberName));
}
}
else
{
// Must be ignored
return ValidationResult.Success;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.