Asp.net mvc MVC 3.0中的运行时条件验证(必填字段)

Asp.net mvc MVC 3.0中的运行时条件验证(必填字段),asp.net-mvc,asp.net-mvc-3,validation,Asp.net Mvc,Asp.net Mvc 3,Validation,我的模型类中几乎没有地址行字段,这会根据所选国家/语言更改其行为(必需/非必需) 例如,英国应该有3个地址行作为必填输入字段,而在美国,它应该只有2个必填字段 我曾尝试使用自定义验证器“RequiredIf”&根据另一个可为null的布尔属性打开或关闭它;但它不起作用 我的模型的相关属性包括: public bool? IsAddressLine3Mandatory { get; set; } [RequiredIf("IsAddressline3Mandatory", true, Error

我的模型类中几乎没有地址行字段,这会根据所选国家/语言更改其行为(必需/非必需)

例如,英国应该有3个地址行作为必填输入字段,而在美国,它应该只有2个必填字段

我曾尝试使用自定义验证器“RequiredIf”&根据另一个可为null的布尔属性打开或关闭它;但它不起作用

我的模型的相关属性包括:

public bool? IsAddressLine3Mandatory { get; set; }

[RequiredIf("IsAddressline3Mandatory", true, ErrorMessage = "Address line 3 is mandatory for UK")]
    public string AddressLine3 { get; set; }
我正在从数据库中获取国家信息,并在HTTPGet操作方法中为该视图设置IsAddressline3Mandatory字段

我试图实现客户端和服务器端的验证

RequiredIf的代码如下所示:

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

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // get a reference to the property this validation depends upon
        var containerType = validationContext.ObjectInstance.GetType();
        var field = containerType.GetProperty(this.DependentProperty);

        if (field != null)
        {
            // get the value of the dependent property
            var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);

            // compare the value against the target value
            if ((dependentvalue == null && this.TargetValue == null) ||
                (dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
            {
                // match => means we should try validating this field
                if (!_innerAttribute.IsValid(value))
                    // validation failed - return an error
                    return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
            }
        }

        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule()
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "requiredif",
        };

        string depProp = BuildDependentPropertyId(metadata, context as ViewContext);

        // find the value on the control we depend on;
        // if it's a bool, format it javascript style 
        // (the default is True or False!)
        string targetValue = (this.TargetValue ?? "").ToString();
        if (this.TargetValue.GetType() == typeof(bool))
            targetValue = targetValue.ToLower();

        rule.ValidationParameters.Add("dependentproperty", depProp);
        rule.ValidationParameters.Add("targetvalue", targetValue);

        yield return rule;
    }

    private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
    {
        // build the ID of the property
        string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
        // unfortunately this will have the name of the current field appended to the beginning,
        // because the TemplateInfo's context has had this fieldname appended to it. Instead, we
        // want to get the context as though it was one level higher (i.e. outside the current property,
        // which is the containing object (our Person), and hence the same level as the dependent property.
        var thisField = metadata.PropertyName + "_";
        if (depProp.StartsWith(thisField))
            // strip it off again
            depProp = depProp.Substring(thisField.Length);
        return depProp;
    }
}
公共类requireditAttribute:ValidationAttribute,IClientValidable
{
私有RequiredAttribute_innerAttribute=新RequiredAttribute();
公共字符串依赖属性{get;set;}
公共对象TargetValue{get;set;}
public requirediftAttribute(字符串相关属性,对象targetValue)
{
this.DependentProperty=DependentProperty;
this.TargetValue=TargetValue;
}
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext)
{
//获取对此验证所依赖的属性的引用
var containerType=validationContext.ObjectInstance.GetType();
var field=containerType.GetProperty(this.DependentProperty);
如果(字段!=null)
{
//获取依赖属性的值
var dependentvalue=field.GetValue(validationContext.ObjectInstance,null);
//将该值与目标值进行比较
if((dependentvalue==null&&this.TargetValue==null)||
(dependentvalue!=null&&dependentvalue.Equals(this.TargetValue)))
{
//match=>表示我们应该尝试验证此字段
如果(!\u innerAttribute.IsValid(值))
//验证失败-返回错误
返回新的ValidationResult(this.ErrorMessage,new[]{validationContext.MemberName});
}
}
返回ValidationResult.Success;
}
公共IEnumerable GetClientValidationRules(ModelMetadata元数据、ControllerContext上下文)
{
var rule=new ModelClientValidationRule()
{
ErrorMessage=FormatErrorMessage(metadata.GetDisplayName()),
ValidationType=“requiredif”,
};
string depProp=BuildDependentPropertyId(元数据,上下文为ViewContext);
//找到我们所依赖的控件的值;
//如果是bool,则将其格式化为javascript样式
//(默认值为True或False!)
字符串targetValue=(this.targetValue???).ToString();
if(this.TargetValue.GetType()==typeof(bool))
targetValue=targetValue.ToLower();
rule.ValidationParameters.Add(“dependentproperty”,depProp);
规则.ValidationParameters.Add(“targetvalue”,targetvalue);
收益率-收益率规则;
}
私有字符串BuildDependentPropertyId(ModelMetadata元数据,ViewContext)
{
//生成属性的ID
string depProp=viewContext.ViewData.TemplateInfo.GetFullHtmlFieldDid(this.DependentProperty);
//不幸的是,这将在开头追加当前字段的名称,
//因为TemplateInfo的上下文已经附加了这个字段名
//想要获得更高一级的上下文(即在当前属性之外,
//它是包含对象(我们的人),因此与从属属性处于同一级别。
var thisField=metadata.PropertyName+“\uux”;
if(depProp.StartsWith(此字段))
//再把它剥掉
depProp=depProp.Substring(thisField.Length);
返回depProp;
}
}

您可以展示您的模型吗?另外,您如何根据国家/地区选择来切换
IsAddressline3Mandatory
属性的值?@DarinDimitrov:我已经添加了相关的模型属性。我正在从我们的数据库中获取国家/地区信息,并在HTTPGet操作方法中为在视图中。但是用户可以在视图中更改国家,对吗?在这种情况下,您如何更新此属性值?@DarinDimitrov:不,我们没有为用户提供此选项。(他不能自己更改国家)。