在我的MVC项目中,我有一个页面,该页面使用Html.EditorFor()和EditorTemplate创建不同数量的复选框。它从数据库中获取数据。
还有一个允许注释的字符串属性。
如果选中了任何复选框,则必须提供注释。
我以前使用过自定义验证,但这是我第一次在集合上尝试使用它,我不确定如何提取集合以测试是否选中了任何复选框。 (在这种情况下,“ IsSelected”是否为真。
public class ValidationOptionViewModel
{
public int OptionId { get; set; }
public string Description { get; set; }
public string Keyword { get; set; }
public bool IsSelected { get; set; }
public bool IsCompulsory { get; set; }
public bool IsBlocking { get; set; }
}
public class AnatomyViewModel
{
public int Id { get; set; }
public ICollection<ValidationOptionViewModel> ValidationOptions { get; set; }
[Display(Name = "Bypass Validation Reason")]
[BypassReasonRequiredIfNoneSelected("ValidationOptions", "BypassValidationReason", ErrorMessage = "A Bypass reason is required when bypassing validations.")]
public string BypassValidationReason { get; set; }
}
自定义验证:
public class BypassReasonRequiredIfNoneSelected : ValidationAttribute, IClientValidatable
{
private readonly string[] _properties;
public BypassReasonRequiredIfNoneSelected(params string[] properties)
{
_properties = properties;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (_properties == null || _properties.Length < 1)
{
return null;
}
//The below works for a string value...
//var actionPropertyInfo = validationContext.ObjectType.GetProperty(_properties[0]);
//var actionValue = actionPropertyInfo.GetValue(validationContext.ObjectInstance, null).ToString();
// What I need in pseudo-code
// Extract the data in type List<ValidationOptionViewModel>
// Iterate and see if any 'IsSelected' are true;
// If any are selected, make sure BypassValidationReason has text etc...
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "atleastonerequired"
};
rule.ValidationParameters["properties"] = string.Join(",", _properties);
yield return rule;
}
}
编辑1
几乎是 facepalm 。下面是窍门。
var actionPropertyInfo = validationContext.ObjectType.GetProperty(_properties[0]);
List<ValidationOptionViewModel> options = actionPropertyInfo.GetValue(validationContext.ObjectInstance, null) as List<ValidationOptionViewModel>;
答案 0 :(得分:0)
下面的“自定义验证”解决了该问题。
public class BypassReasonRequiredIfNoneSelected : ValidationAttribute, IClientValidatable
{
private readonly string[] _properties;
public BypassReasonRequiredIfNoneSelected(params string[] properties)
{
_properties = properties;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (_properties == null || _properties.Length < 1)
{
return null;
}
var actionPropertyInfo = validationContext.ObjectType.GetProperty(_properties[0]);
List<ValidationOptionViewModel> options = actionPropertyInfo.GetValue(validationContext.ObjectInstance, null) as List<ValidationOptionViewModel>;
if (options.Where(x => x.IsSelected == true).Any())
{
var reasonPropertyInfo = validationContext.ObjectType.GetProperty(_properties[1]);
string reasonValue = reasonPropertyInfo.GetValue(validationContext.ObjectInstance, null) == null ? "" : reasonPropertyInfo.GetValue(validationContext.ObjectInstance, null).ToString();
if (String.IsNullOrEmpty(reasonValue))
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
return null;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessage,
ValidationType = "atleastonerequired"
};
rule.ValidationParameters["properties"] = string.Join(",", _properties);
yield return rule;
}
}