c# - 如何使我的自定义数据注释起作用(它在列表中,列表中的每个项目都会覆盖最后的验证测试)

标签 c# asp.net-mvc validation asp.net-mvc-3 data-annotations

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

我想让它做什么。

  1. 被设置在一个属性上(现在我只能弄清楚如何在类里面实现)
  2. 要足够聪明,意识到正在使用多个实例。

场景

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

下拉列表中的值是相同的。 (“天”和“分钟”)

现在用户在 textbox1 中键入 30 并在 ddl1 中选择“days”。然后,他在 textbox2 中键入 10000 并在 ddl2 中键入“days”。第一个有效,第二个无效,因为一年只有 365 天。

场景二

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

因此,他们可以选择有效日期和无效分钟时间的任意组合。

或者两者都有效

到目前为止,我有这个

我的 View 模型

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

        public string ReminderLength { get; set; }
    }

这将在 View 模型列表中并生成我需要的数量

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

查看

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

问题一

如您所见,我在类上有注释,我宁愿在 ReminderLength 属性上有注释。

问题2

现在我只有 30 天了,所以打字比较少(我稍后会更改)。我现在发现的问题是,如果 textbox1 中有 31,这将使我的验证失败。

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

不正确的是它将覆盖第一个无效验证。所以现在它认为所有验证都通过并进入我的操作方法。当它应该拒绝它并返回 View 并告诉用户 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;
    } 
}

现在在您的 ViewModel 中,您可以像这样注释 ReminderLength 属性:

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

当验证取决于另一个属性的值时,我通常会这样做。 GetClientValidationRules 方法是您需要通过 jquery validate 绑定(bind)到不显眼的客户端验证的服务器端部分。 查看此链接以获取另一个 ValidationAttribute 示例:http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2

本网站上的示例还涉及编写必要的 jQuery 以绑定(bind)客户端验证

关于c# - 如何使我的自定义数据注释起作用(它在列表中,列表中的每个项目都会覆盖最后的验证测试),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4916467/

相关文章:

c# - C# 中 pretty-print 异常

c# - 没有 child 的情况下如何查找家长记录?

c# - 作为遗留 ASP.NET MVC 应用程序的一部分时,如何在 Web API 2 中对用户进行身份验证?

java - 如何在不使用控制流异常的情况下根据模式验证 XML?

c# - SQL Server 2008 从大于给定日期时间的返回值中选择最小值

c# - MVC3 Json 绑定(bind)错误?

javascript - 禁用多个下拉列表中的选定项目

asp.net-mvc - 带有在 Azure 上运行的 razor 的 ASP MVC3

php检查变量是否为整数

javascript - 如何在在线表单中验证验证码