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

86

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

Каков способ MVC сделать это с аннотацией данных?

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

  • 2
    Вы смотрели на свободную проверку? Он обрабатывает сложные сценарии намного лучше, чем аннотации данных
  • 0
    Взгляните на очень рекомендуемые решения .... dotnetcurry.com/ShowArticle.aspx?ID=776
Показать ещё 1 комментарий
Теги:
asp.net-mvc
data-annotations
asp.net-mvc-3

6 ответов

133
Лучший ответ

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

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; }
}
  • 4
    Спасибо за ответ, я принял ваш ответ. Чувствую себя немного смущенным на самом деле. Вы выписали все решение! Хехе. Нужно было только изменить функцию IsValid, чтобы проверить максимальную длину. Так является ли это приемлемым решением MVC для подобных проблем?
  • 7
    @DannyvanderKraan, да, это общепринятый способ. Конечно, это так ужасно, что я никогда не использую его и вместо этого использую FluentValidation.NET для проверки.
Показать ещё 9 комментариев
73

Авторизованная модель

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

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

  • 0
    Спасибо за ответ Андрею. Хотя ваше решение будет работать, я выберу Дарина, потому что оно более пригодно для повторного использования.
  • 0
    спасибо ваше решение помогло мне !!
Показать ещё 5 комментариев
15

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

[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }
  • 0
    Это великолепно! мои молитвы получили ответ :)
  • 0
    Удивительно! благодарю вас
6

Фон:

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

Надеюсь, это поможет. Приветствия!

Ссылки

0

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

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 = "Er bestaat al een afbeelding met deze naam")]

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

0

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

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")

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

Надеюсь, это поможет!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню