it-roy-ru.com

ASP.NET Core - проверка пользовательской модели

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

if (ModelState.IsValid)

Если мы пометим свойство как [Обязательное], ModelState.IsValid проверит это свойство, если оно содержит значение или нет.

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

Постскриптум Я говорю только о бэкэнд-валидаторе.

8
user2818430

В .NET Core вы можете просто создать класс, наследующий от ValidationAttribute. Вы можете увидеть полную информацию в ASP.NET Core MVC Документы .

Вот пример, взятый прямо из документов:

public class ClassicMovieAttribute : ValidationAttribute
{
    private int _year;

    public ClassicMovieAttribute(int Year)
    {
        _year = Year;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Movie movie = (Movie)validationContext.ObjectInstance;

        if (movie.Genre == Genre.Classic && movie.ReleaseDate.Year > _year)
        {
            return new ValidationResult(GetErrorMessage());
        }

        return ValidationResult.Success;
    }
}

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

Чтобы использовать этот новый атрибут (опять же, взятый из документов), вам нужно добавить его в соответствующее поле:

[ClassicMovie(1960)]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

Вот еще один, более простой пример для гарантии того, что значение равно true:

public class EnforceTrueAttribute : ValidationAttribute
{
    public EnforceTrueAttribute()
        : base("The {0} field must be true.") { }

    public override bool IsValid(object value) =>
        value is bool valueAsBool && valueAsBool;
}

Это применяется так же:

[EnforceTrue]
public bool ThisShouldBeTrue { get; set; }
14
Kirk Larkin

Чтобы создать собственный атрибут проверки в .Net Core, вам нужно наследовать от IModelValidator и реализовать метод Validate.

Пользовательский валидатор

public class ValidUrlAttribute : Attribute, IModelValidator
{
    public string ErrorMessage { get; set; }

    public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
    {
        var url = context.Model as string;
        if (url != null && Uri.IsWellFormedUriString(url, UriKind.Absolute))
        {
            return Enumerable.Empty<ModelValidationResult>();
        }

        return new List<ModelValidationResult>
        {
            new ModelValidationResult(context.ModalMetadata.PropertyName, ErrorMessage)
        };
    }
}

Модель

public class Product
{
    public int ProductId { get; set; }

    [Required]
    public string ProductName { get; set; }

    [Required]
    [ValidUrl]
    public string ProductThumbnailUrl { get; set; }
}

Даст ли этот подход возможность работать со свойством ModelState.IsValid в методе действия контроллера?

Да! Объект ModalState будет правильно отражать ошибки.

Можно ли применить этот подход к модельному классу? Или его можно использовать только со свойствами класса модели?

Я не знаю, можно ли это применить на уровне класса. Я знаю, что вы можете получить информацию о классе от ModalValidationContext хотя:

  • context.Modal: возвращает значение свойства, которое должно быть проверено
  • context.Container: возвращает объект, содержащий свойство
  • context.ActionContext: предоставляет данные контекста и описывает метод действия, который обрабатывает запрос
  • context.ModelMetadata: подробно описывает класс модели, который проверяется

Заметки:

Этот атрибут проверки не работает с проверкой клиента, как было запрошено в OP.

6
David Liang

Я использовал то же решение для проверки NULL, но оно не работает для меня.

using System.ComponentModel.DataAnnotations;

/// <summary>
/// Defines the <see cref="NullCheckAttribute" />
/// </summary>
public class NullCheckAttribute : ValidationAttribute
{
    public NullCheckAttribute()
    : base("The {0} field should not be null.") { }

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

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult("The value should not be null");
        }

        return ValidationResult.Success;
    }
}
0
Muni Chittem