在MVC中,如何验证至少一个复选框与动态创建的复选框一起被选中?

时间:2018-11-19 14:21:07

标签: validation model-view-controller

在我的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>;

1 个答案:

答案 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;
    }
}