ASP.NET MVC: пользовательская проверка с помощью DataAnnotation


У меня есть модель с 4 свойствами, которые имеют тип string. Я знаю, что вы можете проверить длину одного свойства с помощью StringLength аннотации. Однако я хочу проверить длину 4 Свойства в сочетании.

какой способ в MVC, чтобы сделать это с помощью аннотаций данных?

Я спрашиваю об этом, потому что я новичок в MVC и хочу сделать это правильно, прежде чем принимать собственное решение.

6 99

6 ответов:

вы можете написать пользовательский атрибут проверки:

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;
    }
}

и тогда у вас может быть модель представления и украсить ею одно из своих свойств:

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; }
}

собственной обоснованной модели

ваша модель должна реализовать интерфейс 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) });
    }
}

обратите внимание: это на стороне сервера проверка. Он не работает на стороне клиента. Проверка будет выполнена только после отправки формы.

ExpressiveAnnotations дает вам такую возможность:

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

Справочная информация:

проверки модели необходимы для обеспечения того, что полученные данные мы получаем действительны и правильны, так что мы можем сделать дальнейшую обработку с этими данными. Мы можем проверить модель в методе действия. Встроенные атрибуты проверки-Compare, Range, RegularExpression, Required, StringLength. Однако у нас могут быть сценарии, в которых нам требуются атрибуты проверки, отличные от встроенных.

Выборочная Проверка Атрибуты

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;}
}

чтобы создать пользовательский атрибут проверки, вам придется наследовать этот класс от 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;
    }
}

надеюсь, что это помогает. Ура !

ссылки

чтобы улучшить ответ Дарина, он может быть немного короче:

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

модель:

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

обратите внимание, что сообщение об ошибке не требуется, в противном случае ошибка будет пустой.

немного поздно, чтобы ответить, но для тех, кто ищет. Вы можете легко сделать это, используя дополнительное свойство с аннотацией данных:

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

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

это все слишком реально. Если вы действительно хотите отобразить в определенном месте ошибку проверки, вы можете добавить это в своем представлении:

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

делаю это в представлении может пригодиться, если вы хотите сделать локализацию.

надеюсь, что это помогает!