MVC RequiredIf Attribute - IsValid value parameter always null

user2166297 picture user2166297 · Jun 3, 2014 · Viewed 7.1k times · Source

I am implementing a RequiredIf validation attribute and the value being passed to the IsValid method is always 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);
    }
}

ViewModel

        [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)

Every time the form is submitted, the RequiredIf error message is thrown and I have a feeling it has to do with the null value I described initially. What am I doing wrong? Thanks!

NOTE: The HTML appears to be rendering properly, so I don't think that's the problem.

    <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>

Answer

brainless coder picture brainless coder · Jun 3, 2014

Because this is your code -

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);
    }
}

You are using a RequriedAtrribute. So to simulate that it behaves life a RequiredIf you have to implement some logic that will check whether the target property value is true or false. But you are not doing that and returning just from the innerattribute. So it is just a mere Required not RequiredIf -

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

modify this function to do some checking like -

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