Asp.net mvc 4 MVC RequiredIf属性-IsValid值参数始终为空

Asp.net mvc 4 MVC RequiredIf属性-IsValid值参数始终为空,asp.net-mvc-4,data-annotations,validationattribute,Asp.net Mvc 4,Data Annotations,Validationattribute,我正在实现一个RequiredIf验证属性,传递给IsValid方法的值始终为null 要求属性类 public class RequiredIfAttribute : ValidationAttribute { private RequiredAttribute innerAttribute = new RequiredAttribute(); public string DependentProperty { get; set; } public object

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

要求属性类

    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; }
编辑模板

    @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错误消息,我感觉这与我最初描述的空值有关。我做错了什么?谢谢

注意: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>

因为这是你的密码-

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);
    }
}
您正在使用RequiredAttribute。因此,为了模拟它的行为,如果你必须实现一些逻辑来检查目标属性值是真是假。但您并没有这样做,只是从innerattribute返回。因此,这只是一个要求,而不是要求-

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

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

我使用以下代码:

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

我不打算用这个实现客户端验证,我们的服务器端验证属性也有一个非常类似的实现。我感谢你的发帖,但我在这里没有看到解决方案。谢谢,但我的代码与其他字段一样工作,所以我认为你用这个解决方案找错了方向。这似乎与以下事实有关:该字段可以为空,或者它可以为空,并且使用下拉菜单作为选择机制。@domroco您选错了树。无脑编码器是100%正确的。
[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; }

    // . . .
}