Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使我的自定义数据批注工作(它位于列表中,列表中的每个项目都会覆盖上一个验证测试)_C#_Asp.net Mvc_Validation_Asp.net Mvc 3_Data Annotations - Fatal编程技术网

C# 如何使我的自定义数据批注工作(它位于列表中,列表中的每个项目都会覆盖上一个验证测试)

C# 如何使我的自定义数据批注工作(它位于列表中,列表中的每个项目都会覆盖上一个验证测试),c#,asp.net-mvc,validation,asp.net-mvc-3,data-annotations,C#,Asp.net Mvc,Validation,Asp.net Mvc 3,Data Annotations,我在asp.net mvc 3.0中的自定义验证遇到问题 我想让它做什么 在属性上设置(现在我只知道如何在类上设置) 要足够聪明,意识到有多个实例正在使用 场景 textbox(id=“textbox1”) 下拉列表(id=“ddl1”) textbox(id=“textbox2”) 4下拉列表(id=“ddl2”) dropdownlist中的值相同。(“天”和“分钟”) 现在用户在TextBox130中键入,并在ddl1中选择“天”。然后,他在文本框2中键入10000,在ddl2中键入“天”

我在asp.net mvc 3.0中的自定义验证遇到问题

我想让它做什么

  • 在属性上设置(现在我只知道如何在类上设置)
  • 要足够聪明,意识到有多个实例正在使用
  • 场景

  • textbox(id=“textbox1”)
  • 下拉列表(id=“ddl1”)
  • textbox(id=“textbox2”) 4下拉列表(id=“ddl2”)
  • dropdownlist中的值相同。(“天”和“分钟”)

    现在用户在TextBox130中键入,并在ddl1中选择“天”。然后,他在文本框2中键入10000,在ddl2中键入“天”。第一个有效第二个无效,因为一年中只有365天

    场景2

    用户在Texbox199中键入,并在ddl1中选择“分钟”。这当然是无效的,应该失败

    所以他们可以选择一个有效的日期和一个无效的分钟时间

    或者两者都是有效的

    到目前为止我有这个

    我的viewmodel

      [ReminderFormat(ErrorMessage =  "test")]
        public class ReminderViewModel
        {
            public List<SelectListItem> DurationTypes { get; set; }
            public DurationTypes SelectedDurationType { get; set; }
    
            public string ReminderLength { get; set; }
        }
    
    问题1

    如您所见,我在类上有注释,而在提醒长度属性上有注释

    问题2

    现在我只有30天的时间,所以打字就少了(我以后会修改)。我现在发现的问题是,如果textbox1中有31个,那么我的验证就会失败

    这是正确的。但如果textbox2的值为1,它将通过验证。这也是正确的


    不正确的是,它将覆盖第一个无效验证。所以现在它认为所有的验证都通过了,并进入了我的操作方法。当它应该拒绝它并返回视图并告诉用户textbox1未通过验证时。

    以下是我将如何处理您的验证属性:

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class ReminderFormatAttribute: ValidationAttribute, IClientValidatable
    {
        public string DurationProperty { get; set; }
    
        public ReminderFormatAttribute(string durationProperty)
        {
            DurationProperty = durationProperty;
            ErrorMessage = "{0} value doesn't work for selected duration";
        }
    
        public override string FormatErrorMessage(string propName)
        {
            return string.Format(ErrorMessage, propName);
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var durationType = validationContext.ObjectType.GetProperty(DurationProperty).GetValue(validationContext.ObjectInstance, null);
            var reminderLength = value;
    
            // Do your switch statement on durationType here
            // Here is a sample of the correct return values
            switch (durationType)
            {
                case DurationTypes.Days:
                    if (reminderLength > 30)
                    {
                        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                    }
                    else
                    {
                        return null;
                    }
            }
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
                          {
                            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                            ValidationType = "reminderformat",
                          };
            rule.ValidationParameters["durationproperty"] = DurationProperty;
            yield return rule;
        } 
    }
    
    当验证取决于另一个属性的值时,我通常就是这样做的。GetClientValidationRules方法是服务器端的一部分,您需要通过jQueryValidate连接到不引人注目的客户端验证中。 查看此链接了解另一个ValidationAttribute示例:


    这个网站上的例子还用于编写必要的jQuery以配合客户机验证

    我在MVC2中的一个项目中工作,在那里我们有非常复杂的验证规则,许多规则(一些愚蠢的;-)和许多依赖性。。。。。最后,我发现使用fluent验证框架check更容易完成这种验证htt://fluentvalidation.codeplex.com@Dai-Bok-有趣的是,我看到它适用于客户端,但我没有看到任何示例。它是否使用jquery验证和通畅的javascript?@chobo2。在这一点上,我可能已经过时了,但上次我看到这一点时,没有使用复杂规则进行客户端验证的框架,特别是应用程序核心中的其他对象的依赖性。在FV中可以进行简单的客户端验证,例如最大长度、范围或正则表达式。这里是一个MVC@Dai-Bok的例子-除非它是内置的受支持的复杂验证,否则应该有。然而,如果它是定制的,那么当然不是,因为您需要构建服务器端和客户端。因此,我想知道我是否可以自己进行验证如果我使用fluent,我可以编写jquery验证部分来执行客户端吗?是的,我们提出了一个解决方案,基本上是编写自定义jquery客户端验证脚本,并将此脚本包含在需要它们的页面上。这是一个特定的jquery脚本,与我们的自定义fluentvalidation分离(打破了干式:-(两组验证的原则)。另一种方法是编写一个解析器来解析自定义fluentvalidation规则(甚至自定义数据注释)并生成验证页面所需的适当的非突兀JQuery Javascript。
    // do a for loop through the viewModel (  List<ReminderViewModel> )
    // generate a textbox html box and drop down list for each one
    
        // set attribute to class for now but I want it on a property but I can't
        // figure out how to get SelectedDurationType  and pass it in. if I have my attribute on ReminderLength 
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    
    public class ReminderFormatAttribute : ValidationAttribute
    {
    
        public override bool IsValid(object value)
        {
    
            var reminderViewModel = (ReminderViewModel)value;
    
    
            switch (reminderViewModel.SelectedDurationType)
            {
                case DurationTypes.Days:
                    int length = Convert.ToInt32(reminderViewModel.ReminderLength);
                    if (length > 30)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class ReminderFormatAttribute: ValidationAttribute, IClientValidatable
    {
        public string DurationProperty { get; set; }
    
        public ReminderFormatAttribute(string durationProperty)
        {
            DurationProperty = durationProperty;
            ErrorMessage = "{0} value doesn't work for selected duration";
        }
    
        public override string FormatErrorMessage(string propName)
        {
            return string.Format(ErrorMessage, propName);
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var durationType = validationContext.ObjectType.GetProperty(DurationProperty).GetValue(validationContext.ObjectInstance, null);
            var reminderLength = value;
    
            // Do your switch statement on durationType here
            // Here is a sample of the correct return values
            switch (durationType)
            {
                case DurationTypes.Days:
                    if (reminderLength > 30)
                    {
                        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                    }
                    else
                    {
                        return null;
                    }
            }
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
                          {
                            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                            ValidationType = "reminderformat",
                          };
            rule.ValidationParameters["durationproperty"] = DurationProperty;
            yield return rule;
        } 
    }
    
    [ReminderFormat("SelectedDurationType")]
    public string ReminderLength { get; set; }