.NET Range 和 StringLength 属性可以在 MVC 应用程序之外使用吗?

问题描述 投票:0回答:2

我想使用 .NET StringLengthRange 属性对我的类中的各种属性施加约束。我写了以下非常简单的代码:

class AttributePlayground
{
    [StringLength(5)]
    public static String StringLengthTest { get; set; }

    [Range(10, 20)]
    public static int Age { get; set; }
}

static void Main(string[] args)
{
    AttributePlayground.StringLengthTest = "Too long!";
    AttributePlayground.Age = 34;    
}

我预计会发生错误或异常,但一切正常。

我在网上看到的有关这些属性的所有示例都在 MVC 上下文中显示了它们,但文档没有引用它。

asp.net-mvc attributes
2个回答
3
投票

如您所知,.NET 中的属性只是在编译时嵌入到程序集中的元数据。如果没有任何东西可以解释它们,那么什么也不会发生。

因此,以 ASP.NET MVC 为例,有一个验证器可以解释这些属性,如下所示:

class AttributePlayground
{
    [StringLength(5)]
    public String StringLengthTest { get; set; }

    [Range(10, 20)]
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        var attributePlayground = new AttributePlayground();
        attributePlayground.StringLengthTest = "Too long!";
        attributePlayground.Age = 34;

        var context = new ValidationContext(attributePlayground, null, null);
        var errors = new List<ValidationResult>();
        if (!Validator.TryValidateObject(attributePlayground, context, errors, true))
        {
            foreach (var error in errors)
            {
                Console.WriteLine(error.ErrorMessage);
            }
        }
    }
}

但老实说,如果您打算进行一些更严肃和复杂的验证,我建议您不要使用声明性验证逻辑,这就是数据注释。我会推荐您FluentValidation.NET。它允许您以一种很好的方式表达更复杂的验证规则,否则使用数据注释很难实现。


0
投票

是的,这是可能的。这是一个老问题,但谷歌搜索让我来到这里,我将为未来的读者留下答案。 如果您在 ASP 之外,则需要自己调用验证器。这是如何做到的:

using System;
using System.Globalization;
using System.Reflection;
using System.ComponentModel.DataAnnotations;

class AttributePlayground
{
    private String _stringLengthTest;
    [StringLength(5)]
    public String StringLengthTest {
        get { return _stringLengthTest; }
        set { _stringLengthTest = value; ValidateProperty("StringLengthTest"); }
    }

    private int _age;
    [Range(10, 20)]
    public int Age {
        get { return _age; }
        set { _age = value; ValidateProperty("Age"); }
    }

    private void ValidateProperty(string propName)
    {
        PropertyInfo propInfo = this.GetType().GetProperty(propName);
        Object[] attributes = propInfo.GetCustomAttributes(true);
        foreach (Object attribute in attributes)
        {
            ValidationAttribute vattr = attribute as ValidationAttribute;
            if (vattr != null)
            {
                object propValue = propInfo.GetValue(this, null);
                vattr.Validate(propValue, propInfo.Name);
            }
        }
    }
}

每当在属性分配期间遇到属性限制时,这都会产生一个很好的 ValidationException。如果您愿意,可以将验证方法设为静态并传递

this
作为参数。

另请参阅这个问题,了解如何使用 DataAnnotations.Validator 类手动验证。

这不在问题范围内,但也可以使用自定义属性。这是一个简短的例子:

// Introduce the [StringLengthIs(number)] attribute:
sealed public class StringLengthIsAttribute : ValidationAttribute
{
    public int Length { get; private set; }
    public StringLengthIsAttribute(int len)
    {
        ErrorMessage = "The field {0} must be a string with a length of {1}.";
        Length = len;
    }
    public override bool IsValid(object value)
    {
        if (value == null) return false;
        return value.ToString().Length == Length;
    }
    public override string FormatErrorMessage(string name)
    {
        return string.Format(CultureInfo.CurrentCulture,
          ErrorMessageString, name, Length);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.