DataAnnotations 中的必需属性似乎不起作用

发布于 2024-09-06 17:16:07 字数 3532 浏览 5 评论 0原文

我有一个我创建的 DataAnnotationValidator。我目前正在尝试使用“必填字段”属性对其进行测试,当我的属性为 null 时,我无法让 IsValid 属性失败。当我创建一个具有超出指定范围的范围属性的数字时,它确实可以正常工作。

public class TestEntityWithDataAnnotations
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "Required")]
    public string Name { get; set; }
}

[TestFixture]
public class DataAnnotationValidatorTest
{
    [Test]
    public void Validate_ReturnsFailure_WhenPropertyValidationIsNotValid()
    {
        var validator = new DataAnnotationValidator();
        var invalidEntity = new TestEntityWithDataAnnotations
        {
            Id = Guid.NewGuid()
        };
        var validationResult = validator.Validate(invalidEntity);

        Assert.IsFalse(validationResult.IsValid);
    }
}

public class DataAnnotationValidator
{
    public ValidationResult Validate(object obj)
    {
        Type objType = obj.GetType();            
        var typeDescriptor = GetTypeDescriptor(obj, objType);
        var validationResult = new ValidationResult();

        var classValidationResult = CheckClassIsValid(obj, typeDescriptor);
        if (!classValidationResult.IsValid)
        {
            validationResult.AddErrors(classValidationResult.Errors);
        }
        foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.GetProperties())
        {
            // Loop over all of the properties on our object that have Validation Attributes
            var propValidationResult = CheckPropertyIsValid(obj, propertyDescriptor);
            if(!propValidationResult.IsValid)
            {
                validationResult.AddErrors(propValidationResult.Errors);
            }
        }
        return validationResult;
    }

    /// <summary>
    /// Checks to see if there are any class level validation attributes and runs them
    /// </summary>
    /// <returns></returns>
    private static ValidationResult CheckClassIsValid(object obj, ICustomTypeDescriptor typeDescriptor)
    {
        var errors = typeDescriptor.GetAttributes().OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(obj))
            .Select(x => new ValidationError(typeDescriptor.GetClassName(), x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }

    /// <summary>
    /// Checks to see if a property has any DataAnnotations that it has violated
    /// </summary>
    private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor)
    {
        var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(obj))
            .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }

    /// <summary>
    /// Gets the model's type descriptor. In order to support the buddy class metadata model
    /// for LINQ to SQL and Entity Framework, it uses
    /// <see cref="AssociatedMetadataTypeTypeDescriptionProvider"/>.
    /// </summary>
    /// <param name="obj">The model object</param>
    /// <param name="objType">The type of the model object</param>
    /// <returns>The model's type descriptor</returns>
    private static ICustomTypeDescriptor GetTypeDescriptor(object obj, Type objType)
    {
        var provider = new AssociatedMetadataTypeTypeDescriptionProvider(objType);
        return provider.GetTypeDescriptor(objType, obj);
    }
}

I have a DataAnnotationValidator that I created. I am currently trying to test it with a Required Field attribute and I can't get the IsValid property to fail when my property is null. It does work correctly when I create a number with a Range attribute that is outside of the specified Range.

public class TestEntityWithDataAnnotations
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "Required")]
    public string Name { get; set; }
}

[TestFixture]
public class DataAnnotationValidatorTest
{
    [Test]
    public void Validate_ReturnsFailure_WhenPropertyValidationIsNotValid()
    {
        var validator = new DataAnnotationValidator();
        var invalidEntity = new TestEntityWithDataAnnotations
        {
            Id = Guid.NewGuid()
        };
        var validationResult = validator.Validate(invalidEntity);

        Assert.IsFalse(validationResult.IsValid);
    }
}

public class DataAnnotationValidator
{
    public ValidationResult Validate(object obj)
    {
        Type objType = obj.GetType();            
        var typeDescriptor = GetTypeDescriptor(obj, objType);
        var validationResult = new ValidationResult();

        var classValidationResult = CheckClassIsValid(obj, typeDescriptor);
        if (!classValidationResult.IsValid)
        {
            validationResult.AddErrors(classValidationResult.Errors);
        }
        foreach (PropertyDescriptor propertyDescriptor in typeDescriptor.GetProperties())
        {
            // Loop over all of the properties on our object that have Validation Attributes
            var propValidationResult = CheckPropertyIsValid(obj, propertyDescriptor);
            if(!propValidationResult.IsValid)
            {
                validationResult.AddErrors(propValidationResult.Errors);
            }
        }
        return validationResult;
    }

    /// <summary>
    /// Checks to see if there are any class level validation attributes and runs them
    /// </summary>
    /// <returns></returns>
    private static ValidationResult CheckClassIsValid(object obj, ICustomTypeDescriptor typeDescriptor)
    {
        var errors = typeDescriptor.GetAttributes().OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(obj))
            .Select(x => new ValidationError(typeDescriptor.GetClassName(), x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }

    /// <summary>
    /// Checks to see if a property has any DataAnnotations that it has violated
    /// </summary>
    private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor)
    {
        var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(obj))
            .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }

    /// <summary>
    /// Gets the model's type descriptor. In order to support the buddy class metadata model
    /// for LINQ to SQL and Entity Framework, it uses
    /// <see cref="AssociatedMetadataTypeTypeDescriptionProvider"/>.
    /// </summary>
    /// <param name="obj">The model object</param>
    /// <param name="objType">The type of the model object</param>
    /// <returns>The model's type descriptor</returns>
    private static ICustomTypeDescriptor GetTypeDescriptor(object obj, Type objType)
    {
        var provider = new AssociatedMetadataTypeTypeDescriptionProvider(objType);
        return provider.GetTypeDescriptor(objType, obj);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瑕疵 2024-09-13 17:16:08

我有点愚蠢。我需要将属性的值传递到 CheckPropertyIsValid 内部的 IsValid 而不是整个对象。

private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor)
    {
        var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(propertyDescriptor.GetValue(obj)))
            .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }

A bit of stupidity on my part. I needed to pass the value of the property into IsValid inside of CheckPropertyIsValid instead of the whole object.

private static ValidationResult CheckPropertyIsValid(object obj, PropertyDescriptor propertyDescriptor)
    {
        var errors = propertyDescriptor.Attributes.OfType<ValidationAttribute>()
            .Where(x => !x.IsValid(propertyDescriptor.GetValue(obj)))
            .Select(x => new ValidationError(propertyDescriptor.Name, x.ErrorMessage));
        return new ValidationResult(errors.ToList());
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文