Asp.net mvc 2 MVC2:具有两个字段依赖关系的验证(数据注释)

Asp.net mvc 2 MVC2:具有两个字段依赖关系的验证(数据注释),asp.net-mvc-2,Asp.net Mvc 2,例如: 我们有一个条件字段。 此条件字段是一个单选按钮,具有以下两个值“是”和“否”。 假设这个单选按钮的名字是“AAA” 只有当另一个单选按钮字段“BBB”设置为“是”时,才应显示此条件字段“AAA”。(单选按钮“BBB”的值也是“是”和“否”) 但条件字段“AAA”应显示为无预设值,表示首次显示字段时应设置“是”或“否” 出现此问题的原因是,只有当(非条件)字段“BBB”设置为“是”时,才需要条件字段“AAA”,而当字段“BBB”设置为“否”时,则不需要条件字段“AAA” (听起来,我没有听

例如: 我们有一个条件字段。 此条件字段是一个单选按钮,具有以下两个值“是”和“否”。 假设这个单选按钮的名字是“AAA”

只有当另一个单选按钮字段“BBB”设置为“是”时,才应显示此条件字段“AAA”。(单选按钮“BBB”的值也是“是”和“否”)

但条件字段“AAA”应显示为无预设值,表示首次显示字段时应设置“是”或“否”

出现此问题的原因是,只有当(非条件)字段“BBB”设置为“是”时,才需要条件字段“AAA”,而当字段“BBB”设置为“否”时,则不需要条件字段“AAA”

(听起来,我没有听到任何关于if语句的消息,或者?但是请坚持并继续阅读…)

相信我,当我们使用“Modelstate”时,解决这个问题对我来说并不是一个问题,但我们在这里讨论的是验证(数据注释),看起来像这样:

public class Input1FormModel 
{
     [Required(ErrorMessageResourceName="Error_Field_AAA_Empty",
               ErrorMessageResourceType=typeof(Resources.MyDialog))]
     public int AAA { get; set; }
}
我也完全理解这些代码行-我相信;-)

但是,如何解决上述依赖关系(AAA BBB)


将“return DateTime.Now.Year;”更改为先检查另一个字段然后返回true或false的函数调用?但是如何获取其他字段的值呢?

您可能需要使用IDataErrorInfo

看,我回答了这个问题:


查看并回答我提出的这个问题。

您可以使用数据注释来完成此操作,但是注释需要在类级别上操作,而不是在属性级别上操作,因为ValidationAttribute用于单个属性

这里是我创建的一个示例,因为邮政编码是可选的,如果人们说他们在新西兰,则不需要说明,但在澳大利亚是强制性的。此复合验证将整个模型作为输入值,并使用反射来比较从数据注释传入的属性名称的值

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class NZPostcodeAttribute : ValidationAttribute
{
    public const string _defaultErrorMessage = "Postcode and State are required for Australian residents";
    private readonly object _typeId = new object();

    public NZPostcodeAttribute(string countryProperty, string postcodeProperty, string stateProperty)
    {
        CountryProperty = countryProperty;
        PostcodeProperty = postcodeProperty;
        StateProperty = stateProperty;
    }

    public string CountryProperty { get; private set; }
    public string StateProperty { get; private set; }
    public string PostcodeProperty { get; private set; }

    public override object TypeId
    {
        get
        {
            return _typeId;
        }
    }

    public override string FormatErrorMessage(string name)
    {
        return _defaultErrorMessage;
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value);
        object countryValue = props.Find(CountryProperty, true).GetValue(value);
        object postcodeValue = props.Find(PostcodeProperty, true).GetValue(value);
        object stateValue = props.Find(StateProperty, true).GetValue(value);

        string countryString = countryValue == null ? "" : countryValue.ToString();
        string postcodeString = postcodeValue == null ? "" : postcodeValue.ToString();
        string stateString = stateValue == null ? "" : stateValue.ToString();


        bool isValid = true;

        if (countryString.ToString().ToLower() == "australia")
        {
            if (String.IsNullOrEmpty(postcodeString) || String.IsNullOrEmpty(stateString))
            {
                isValid = false;
            }
        }
        if (!String.IsNullOrEmpty(postcodeString))
        {
            string isNumeric = "^[0-9]+";
            if (!Regex.IsMatch(postcodeString, isNumeric))
                isValid = false;
        }
        return isValid;
    }
}
当您想将此应用于模型时,需要在模型的类级别上进行(请参见顶部的标记AttributeTargets.class)

按如下方式操作:

[NZPostcode("Country", "Postcode", "State")]
public class UserRegistrationModel 
{....
您需要将验证属性指向属性名称。也可以在其中添加客户端验证,但这将是一篇完整的文章


您可以轻松地根据您的场景调整上述内容。

thx 4 u非常快速的回复。你是对的。该教程说:“例如,您可能希望强制执行一个验证规则,该规则取决于电影类的多个属性的值”。。。所以这是可能的。另一种解决方法是使用Modelstate,正如我在最初的帖子中所说的。。。但目标是使用像[Required…]或[PropertyComparisonValidator(“LowerBound”,ComparisonOperator.GreaterThan)]这样的属性。。。最后,这不是我的解决方案:-)可能是属性无法解决这个问题。。。还有谁知道呢?但别误会我:谢谢你的回答!!我只是想给你一个替代方法,因为我不知道如何使用属性来实现你的要求。来,看看这个问题/答案:马丁,相信我。我非常感谢你的快速回复和非常好的回答!对不起,当我在回复中用错了词。这不是我侮辱你的方式。
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class NZPostcodeAttribute : ValidationAttribute
{
    public const string _defaultErrorMessage = "Postcode and State are required for Australian residents";
    private readonly object _typeId = new object();

    public NZPostcodeAttribute(string countryProperty, string postcodeProperty, string stateProperty)
    {
        CountryProperty = countryProperty;
        PostcodeProperty = postcodeProperty;
        StateProperty = stateProperty;
    }

    public string CountryProperty { get; private set; }
    public string StateProperty { get; private set; }
    public string PostcodeProperty { get; private set; }

    public override object TypeId
    {
        get
        {
            return _typeId;
        }
    }

    public override string FormatErrorMessage(string name)
    {
        return _defaultErrorMessage;
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value);
        object countryValue = props.Find(CountryProperty, true).GetValue(value);
        object postcodeValue = props.Find(PostcodeProperty, true).GetValue(value);
        object stateValue = props.Find(StateProperty, true).GetValue(value);

        string countryString = countryValue == null ? "" : countryValue.ToString();
        string postcodeString = postcodeValue == null ? "" : postcodeValue.ToString();
        string stateString = stateValue == null ? "" : stateValue.ToString();


        bool isValid = true;

        if (countryString.ToString().ToLower() == "australia")
        {
            if (String.IsNullOrEmpty(postcodeString) || String.IsNullOrEmpty(stateString))
            {
                isValid = false;
            }
        }
        if (!String.IsNullOrEmpty(postcodeString))
        {
            string isNumeric = "^[0-9]+";
            if (!Regex.IsMatch(postcodeString, isNumeric))
                isValid = false;
        }
        return isValid;
    }
}
[NZPostcode("Country", "Postcode", "State")]
public class UserRegistrationModel 
{....