MVC RequiredIf属性 - IsValid值参数始终为null

时间:2014-06-03 17:12:47

标签: asp.net-mvc-4 data-annotations validationattribute

我正在实现RequiredIf验证属性,并且传递给IsValid方法的值始终为null。

RequiredIfAttribute Class

    public class RequiredIfAttribute : ValidationAttribute
{
    private 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;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }
}

视图模型

        [Required]
    [Display(Name = "Are You A Student?")]
    public bool? IsStudent { get; set; }

    [RequiredIf("IsStudent", true, ErrorMessage = "You must upload a photo of your student ID if you wish to register as a student.")]
    [Display(Name = "Student ID")]
    [FileExtensions("jpg|jpeg|png|pdf", ErrorMessage = "File is not in the correct format.")]
    [MaxFileSize(2 * 1024 * 1024, ErrorMessage = "You may not upload files larger than 2 MB.")]
    public HttpPostedFileBase StudentId { get; set; }

EditorTemplate

    @model bool?
@using System.Web.Mvc;
@{
    var options = new List<SelectListItem>
    {
        new SelectListItem { Text = "Yes", Value = "true", Selected =  Model.HasValue && Model.Value },
        new SelectListItem { Text = "No", Value = "false", Selected =  Model.HasValue && Model.Value }
    };

    string defaultOption = null;

    if (ViewData.ModelMetadata.IsNullableValueType)
    {
        defaultOption = "(Select)";
    }
}

@Html.DropDownListFor(m => m, options, defaultOption)

每次提交表单时,都会抛出RequiredIf错误消息,我觉得它与我最初描述的null值有关。我究竟做错了什么?谢谢!

注意:HTML似乎正常呈现,所以我认为这不是问题。

    <select data-val="true" data-val-required="The Are You A Student? field is required." id="IsStudent" name="IsStudent"><option value="">(Select)</option>
<option value="true">Yes</option>
<option value="false">No</option>
</select>

2 个答案:

答案 0 :(得分:2)

因为这是你的代码 -

public class RequiredIfAttribute : ValidationAttribute
{
    private 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;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }
}

您正在使用RequriedAtrribute。因此,要模拟它的行为生命为RequiredIf,您必须实现一些逻辑,以检查目标属性值是true还是false。但是你并没有这样做,只是从内在的回归。所以它只是Required而不是RequiredIf -

public override bool IsValid(object value)
{
    return innerAttribute.IsValid(value);
}

修改此函数以执行某些检查,如 -

public override bool IsValid(object value)
{
    //if the referred property is true then
        return innerAttribute.IsValid(value);
    //else
    return True
}

答案 1 :(得分:0)

我使用以下代码:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public abstract class StefAttribute : ValidationAttribute
{
    public WDCIAttribute()
        : base()
    {
        this.ErrorMessageResourceType = typeof(GlobalResources);
    }
}


[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class StefRequiredIfAttribute : StefAttribute
{
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentProperty { get; set; }
    public object TargetValue { get; set; }

    public WDCIRequiredIfAttribute()
    {
    }

    public WDCIRequiredIfAttribute(string dependentProperty, object targetValue)
        : base()
    {
        this.DependentProperty = dependentProperty;
        this.TargetValue = targetValue;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }
}

public class RequiredIfValidator : DataAnnotationsModelValidator<StefRequiredIfAttribute>
{
    public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, StefRequiredIfAttribute attribute)
        : base(metadata, context, attribute)
    {
    }

    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        // get a reference to the property this validation depends upon
        var field = Metadata.ContainerType.GetProperty(Attribute.DependentProperty);

        if (field != null)
        {
            // get the value of the dependent property
            object value = field.GetValue(container, null);

            // compare the value against the target value
            if (IsEqual(value) || (value == null && Attribute.TargetValue == null))
            {
                // match => means we should try validating this field
                if (!Attribute.IsValid(Metadata.Model))
                {
                    // validation failed - return an error
                    yield return new ModelValidationResult { Message = ErrorMessage };
                }
            }
        }
    }

    private bool IsEqual(object dependentPropertyValue)
    {
        bool isEqual = false;

        if (Attribute.TargetValue != null && Attribute.TargetValue.GetType().IsArray)
        {
            foreach (object o in (Array)Attribute.TargetValue)
            {
                isEqual = o.Equals(dependentPropertyValue);
                if (isEqual)
                {
                    break;
                }
            }
        }
        else
        {
            if (Attribute.TargetValue != null)
            {
                isEqual = Attribute.TargetValue.Equals(dependentPropertyValue);
            }
        }

        return isEqual;
    }
}

可以在模型中使用以下内容:

public class PersonnelVM : EntityVM
{
    // . . .

    [DisplayName("Name")]
    [StefRequiredIf("IndividualOrBulk", PersonnelType.Bulk, ErrorMessageResourceName = GlobalResourceLiterals.Name_Required)]
    public string Name { get; set; }

    [DisplayName("PersonnelType")]
    public PersonnelType IndividualOrBulk { get; set; }

    // . . .
}