使用数据注释自定义模型验证依赖属性

Dar*_*rov 43 validation .net-3.5 data-annotations asp.net-mvc-2

从现在开始,我使用了优秀的FluentValidation 库来验证我的模型类.在Web应用程序中,我将它与jquery.validate插件结合使用,以执行客户端验证.一个缺点是许多验证逻辑在客户端重复,不再集中在一个地方.

出于这个原因,我正在寻找替代方案.有许多例子出表示数据注解的使用来执行模型验证.看起来很有希望.我无法找到的一件事是如何验证依赖于另一个属性值的属性.

我们以下面的模型为例:

public class Event
{
    [Required]
    public DateTime? StartDate { get; set; }
    [Required]
    public DateTime? EndDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想确保EndDate大于StartDate.我可以编写一个扩展ValidationAttribute的自定义验证属性,以便执行自定义验证逻辑.不幸的是我找不到获取模型实例的方法:

public class CustomValidationAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // value represents the property value on which this attribute is applied
        // but how to obtain the object instance to which this property belongs?
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现CustomValidationAttribute似乎可以完成这项工作,因为它具有ValidationContext包含要验证的对象实例的此属性.不幸的是,此属性仅在.NET 4.0中添加.所以我的问题是:我可以在.NET 3.5 SP1中实现相同的功能吗?


更新:

似乎FluentValidation已经支持 ASP.NET MVC 2中的客户端验证和元数据.

尽管数据注释是否可用于验证依赖属性,但仍然很好.

Tra*_*lig 29

MVC2附带了一个示例"PropertiesMustMatchAttribute",它展示了如何让DataAnnotations为您工作,它应该在.NET 3.5和.NET 4.0中都有效.该示例代码如下所示:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute
{
    private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";

    private readonly object _typeId = new object();

    public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
        : base(_defaultErrorMessage)
    {
        OriginalProperty = originalProperty;
        ConfirmProperty = confirmProperty;
    }

    public string ConfirmProperty
    {
        get;
        private set;
    }

    public string OriginalProperty
    {
        get;
        private set;
    }

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

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
            OriginalProperty, ConfirmProperty);
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
        object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
        object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
        return Object.Equals(originalValue, confirmValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

当您使用该属性时,不是将其放在模型类的属性上,而是将其放在类本身上:

[PropertiesMustMatch("NewPassword", "ConfirmPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public class ChangePasswordModel
{
    public string NewPassword { get; set; }
    public string ConfirmPassword { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当在您的自定义属性上调用"IsValid"时,会将整个模型实例传递给它,以便您可以通过这种方式获取依赖属性值.您可以轻松地按照此模式创建日期比较属性,甚至是更一般的比较属性.

Brad Wilson在他的博客上有一个很好的例子,展示了如何添加验证的客户端部分,尽管我不确定该示例是否适用于.NET 3.5和.NET 4.0.

  • 我试过这个,但我永远不会得到验证错误显示在我的aspx页面/视图上.我已经尝试使用空字符串调用validationmessage,也尝试使用验证摘要并且它没有显示(就像在propertiesmustmatch示例中那样) (2认同)

Nic*_*ggs 14

我有这个问题,最近开源我的解决方案:http: //foolproof.codeplex.com/

Foolproof对上述示例的解决方案是:

public class Event
{
    [Required]
    public DateTime? StartDate { get; set; }

    [Required]
    [GreaterThan("StartDate")]
    public DateTime? EndDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


orc*_*rcy 7

而不是PropertiesMustMatch可以在MVC3中使用的CompareAttribute.根据这个链接http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1:

public class RegisterModel
{
    // skipped

    [Required]
    [ValidatePasswordLength]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }                       

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation do not match.")]
    public string ConfirmPassword { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

CompareAttribute是一个新的,非常有用的验证器,它实际上不是System.ComponentModel.DataAnnotations的一部分,但已被团队添加到System.Web.Mvc DLL中.虽然没有特别好的命名(它唯一的比较是检查相等性,所以也许E​​qualTo会更明显),从使用中很容易看出这个验证器检查一个属性的值等于另一个属性的值.您可以从代码中看到,该属性接受一个字符串属性,该属性是您要比较的另一个属性的名称.这种验证器的经典用法是我们在这里使用它:密码确认.