【问题标题】:MVC2: Validation (Data Annotations) with two field dependencyMVC2:具有两个字段依赖性的验证(数据注释)
【发布时间】:2010-09-02 14:13:15
【问题描述】:

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

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

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

问题的出现是基于条件字段“AAA”仅在(非条件)字段“BBB”设置为“yes”时才需要 - 而在字段“BBB”设置时不需要到“不”。

(听起来,我没有听说过关于 if 语句的任何消息,或者?但请继续阅读......)

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

public class Input1FormModel 
{
     [Required(ErrorMessageResourceName="Error_Field_AAA_Empty",
               ErrorMessageResourceType=typeof(Resources.MyDialog))]
     public int AAA { get; set; }
}

我也完全理解这些代码行 - 我相信 ;-)

...

//property limits
public int UpperBound { get { return DateTime.Now.Year; } }
public int LowerBound { get { return 1900; } }

...

[NotNullValidator]
[PropertyComparisonValidator("LowerBound", ComparisonOperator.GreaterThan)]
[PropertyComparisonValidator("UpperBound", ComparisonOperator.LessThanEqual)]
public int? XYZ { get; set; }

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

更改“返回 DateTime.Now.Year;”到一个函数调用,它首先检查另一个字段,然后返回真或假?但是如何获取另一个字段的值呢?

【问题讨论】:

    标签: asp.net-mvc-2


    【解决方案1】:

    您可能需要使用 IDataErrorInfo。

    请参阅this question,我在这里回答了这个问题:

    查看IDataErrorInfo 和我问过的关于IDataErrorInfo vs. DataAnnotations 的问题。

    【讨论】:

    • thx 4 你的回复非常快。你是对的。该教程说:“例如,您可能想要强制执行一个验证规则,该规则取决于 Movie 类的多个属性的值”......所以它是可能的。解决它的另一种方法是使用我在原始帖子中已经说过的 Modelstate ...但目标是使用 [Required ...] 或 [PropertyComparisonValidator("LowerBound",ComparisonOperator.GreaterThan)] 等属性...所以最后这不是我的解决方案 :-) 可能是这无法用属性解决......还有其他任何想法吗?但不要误会我的意思:感谢您的回复/回答!
    • 我只是想为您提供一种替代方法,因为我不知道如何使用属性来完成您的要求。在这里,看看这个问题/答案:stackoverflow.com/questions/1511495/…
    • 马丁,相信我。我非常感谢您的快速回复和非常好的回答!抱歉,当我在回复中使用了错误的词时。这不是我侮辱你的方式。
    【解决方案2】:

    您可以使用数据注释来做到这一点,但注释需要在类级别而不是属性级别上操作,因为验证属性适用于单个属性。

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

        [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 
    {....
    

    您需要将验证属性指向属性名称。也可以为此添加客户端验证,但这本身就是一篇完整的文章。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 2011-03-09
      • 2012-12-29
      • 2017-12-13
      • 2016-05-27
      • 2011-04-27
      相关资源
      最近更新 更多