简体   繁体   English

如何使我的自定义数据批注起作用(它在列表中,列表中的每个项目都覆盖上一个验证测试)

[英]How to make my custom data annotations work( it is in a list and each item in the list overrides the last validation test)

I am having problems with my custom validation in asp.net mvc 3.0 我在asp.net mvc 3.0中的自定义验证遇到问题

What I want to it to do. 我想要它做什么。

  1. Be set on a property (right now I only can figure out how to make it on the class) 在属性上设置(现在我只能弄清楚如何在类上进行设置)
  2. Be smart enough to realize there are multiple instances being used. 足够聪明,以意识到有多个实例正在使用。

Scenario 脚本

  1. textbox ( id = "textbox1") 文本框(id =“ textbox1”)
  2. dropdownlist (id ="ddl1") dropdownlist(id =“ ddl1”)
  3. textbox (id = "textbox2") 4 dropdownlist (id = "ddl2") 文本框(id =“ textbox2”)4下拉列表(id =“ ddl2”)

the values in the dropdownlist are the same. 下拉列表中的值相同。 ("Days" and "Minutes") (“天”和“分钟”)

Now user types in textbox1 30 and chooses "days" in ddl1. 现在,用户输入textbox1 30并在ddl1中选择“天”。 He then types in textbox2 10000 and "days" in ddl2. 然后,他在textbox2中输入10000,在ddl2中输入“ days”。 First one is valid second one is invalid as there is only 365 days in a year. 第一个有效,第二个无效,因为一年只有365天。

Scenario 2 方案2

User types in texbox1 99 and chooses "minutes" in ddl1. 用户输入texbox1 99,并在ddl1中选择“分钟”。 This of course is invalid and should fail. 这当然是无效的,应该会失败。

So there could be any combination of where they might choose a valid day and invalid minute time. 因此,他们可以在其中选择有效日期和无效分钟时间的任意组合。

Or both could be valid 或两者都可能有效

So I have this so far 所以到目前为止

My viewmodel 我的视图模型

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

        public string ReminderLength { get; set; }
    }

This will be in a list of view models and generates the number of ones I need 这将在视图模型列表中,并生成我需要的模型数量

List<ReminderViewModel> viewModel = new List<ReminderViewModel>()
// add ReminderviewModel to this collection

View 视图

// do a for loop through the viewModel (  List<ReminderViewModel> )
// generate a textbox html box and drop down list for each one

Data annotation 数据注解

    // 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();
        }
    }

Problem 1 问题1

So as you can see I have the annotation on the class and I rather have it on the ReminderLength property. 如您所见,我在类上具有注释,而在ReminderLength属性上具有注释。

Problem 2 问题2

Right now I just have days at 30 so it's less to type(I will change it later). 现在我只有30天,所以输入的时间更少了(我稍后会更改)。 The problem I am finding right now is that if textbox1 has 31 in it this will fail my validation. 我现在发现的问题是,如果textbox1中包含31,这将使我的验证失败。

This is correct. 这是对的。 But if I have textbox2 that has 1 as the value it will pass validation. 但是,如果我的textbox2的值为1,它将通过验证。 This is also correct. 这也是正确的。

What is not correct is that it will override the first invalid validation. 不正确的是它将覆盖第一个无效的验证。 So now it thinks all validation passed and goes into my action method. 因此,现在它认为所有验证均已通过,并进入我的操作方法。 When it should reject it and go back to the view and tell the user that textbox1 failed validation. 什么时候应该拒绝它,然后返回视图并告诉用户textbox1验证失败。

Here's what I would do for your validation attribute: 这是我要为您的验证属性执行的操作:

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

Now in your ViewModel you can annotate the ReminderLength property like so: 现在,在您的ViewModel中,您可以像这样注释ReminderLength属性:

[ReminderFormat("SelectedDurationType")]
public string ReminderLength { get; set; }

This is how I usually do it when the validation depends on the value of another property. 当验证取决于另一个属性的值时,这通常是我这样做的方式。 The GetClientValidationRules method is the server side piece you need to tie into the unobtrusive client validation via jquery validate. GetClientValidationRules方法是服务器端的一部分,您需要通过jquery validate绑定到简单的客户端验证中。 Check out this link for another ValidationAttribute example: http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2 查看此链接以获取另一个ValidationAttribute示例: http : //www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2

The example on this site also goes into writing the necessary jQuery to tie in the client validation 该站点上的示例还涉及编写必要的jQuery以配合客户端验证

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM