C# ASP.NET MVC:通过 DataAnnotation 进行自定义验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16100300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:59:47  来源:igfitidea点击:

ASP.NET MVC: Custom Validation by DataAnnotation

c#.netasp.net-mvcasp.net-mvc-3data-annotations

提问by Danny van der Kraan

I have a Model with 4 properties which are of type string. I know you can validate the length of a single property by using the StringLength annotation. However I want to validate the length of the 4 properties combined.

我有一个具有 4 个字符串类型属性的模型。我知道您可以使用 StringLength 注释来验证单个属性的长度。但是我想验证 4 个属性组合的长度。

What is the MVC way to do this with data annotation?

使用数据注释执行此操作的 MVC 方法是什么?

I'm asking this because I'm new to MVC and want to do it the correct way before making my own solution.

我问这个是因为我是 MVC 的新手,想在制定我自己的解决方案之前以正确的方式去做。

采纳答案by Darin Dimitrov

You could write a custom validation attribute:

您可以编写自定义验证属性:

public class CombinedMinLengthAttribute: ValidationAttribute
{
    public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
    {
        this.PropertyNames = propertyNames;
        this.MinLength = minLength;
    }

    public string[] PropertyNames { get; private set; }
    public int MinLength { get; private set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
        var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
        var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
        if (totalLength < this.MinLength)
        {
            return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }
}

and then you might have a view model and decorate one of its properties with it:

然后你可能有一个视图模型并用它装饰它的一个属性:

public class MyViewModel
{
    [CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")]
    public string Foo { get; set; }
    public string Bar { get; set; }
    public string Baz { get; set; }
}

回答by Andrei

Self validated model

自我验证模型

Your model should implement an interface IValidatableObject. Put your validation code in Validatemethod:

您的模型应该实现一个接口IValidatableObject。将您的验证代码放入Validate方法中:

public class MyModel : IValidatableObject
{
    public string Title { get; set; }
    public string Description { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Title == null)
            yield return new ValidationResult("*", new [] { nameof(Title) });

        if (Description == null)
            yield return new ValidationResult("*", new [] { nameof(Description) });
    }
}

Please notice: this is a server-sidevalidation. It doesn't work on client-side. You validation will be performed only after form submission.

请注意:这是服务器端验证。它不适用于客户端。只有在表单提交后才会执行您的验证。

回答by Yasser Shaikh

Background:

背景:

Model validations are required for ensuring that the received data we receive is valid and correct so that we can do the further processing with this data. We can validate a model in an action method. The built-in validation attributes are Compare, Range, RegularExpression, Required, StringLength. However we may have scenarios wherein we required validation attributes other than the built-in ones.

需要模型验证以确保我们收到的接收数据有效且正确,以便我们可以对这些数据进行进一步处理。我们可以在 action 方法中验证模型。内置验证属性是 Compare、Range、RegularExpression、Required、StringLength。但是,我们可能会遇到需要验证属性而不是内置属性的场景。

Custom Validation Attributes

自定义验证属性

public class EmployeeModel 
{
    [Required]
    [UniqueEmailAddress]
    public string EmailAddress {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public int OrganizationId {get;set;}
}

To create a custom validation attribute, you will have to derive this class from ValidationAttribute.

要创建自定义验证属性,您必须从 ValidationAttribute 派生此类。

public class UniqueEmailAddress : ValidationAttribute
{
    private IEmployeeRepository _employeeRepository;
    [Inject]
    public IEmployeeRepository EmployeeRepository
    {
        get { return _employeeRepository; }
        set
        {
            _employeeRepository = value;
        }
    }
    protected override ValidationResult IsValid(object value,
                        ValidationContext validationContext)
    {
        var model = (EmployeeModel)validationContext.ObjectInstance;
        if(model.Field1 == null){
            return new ValidationResult("Field1 is null");
        }
        if(model.Field2 == null){
            return new ValidationResult("Field2 is null");
        }
        if(model.Field3 == null){
            return new ValidationResult("Field3 is null");
        }
        return ValidationResult.Success;
    }
}

Hope this helps. Cheers !

希望这可以帮助。干杯!

References

参考

回答by jwaliszko

ExpressiveAnnotationsgives you such a possibility:

ExpressiveAnnotations为您提供了这样一种可能性:

[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }

回答by Leo Muller

A bit late to answer, but for who is searching. You can easily do this by using an extra property with the data annotation:

回答有点晚,但是谁在搜索。您可以通过对数据注释使用额外的属性来轻松完成此操作:

public string foo { get; set; }
public string bar { get; set; }

[MinLength(20, ErrorMessage = "too short")]
public string foobar 
{ 
    get
    {
        return foo + bar;
    }
}

That's all that is too it really. If you really want to display in a specific place the validation error as well, you can add this in your view:

仅此而已。如果你真的想在特定的地方显示验证错误,你可以在你的视图中添加:

@Html.ValidationMessage("foobar", "your combined text is too short")

doing this in the view can come in handy if you want to do localization.

如果您想进行本地化,在视图中执行此操作会派上用场。

Hope this helps!

希望这可以帮助!

回答by Jamie

To improve Darin's answer, it can be bit shorter:

为了改进 Darin 的答案,它可以缩短一点:

public class UniqueFileName : ValidationAttribute
{
    private readonly NewsService _newsService = new NewsService();

    public override bool IsValid(object value)
    {
        if (value == null) { return false; }

        var file = (HttpPostedFile) value;

        return _newsService.IsFileNameUnique(file.FileName);
    }
}

Model:

模型:

[UniqueFileName(ErrorMessage = "This file name is not unique.")]

Do note that an error message is required, otherwise the error will be empty.

请注意,错误信息是必需的,否则错误将为空。