MVC. net core: Validator.TryValidateObject не проверяет атрибуты, определенные в классе собеседника. - PullRequest
0 голосов
/ 10 марта 2020

Мы использовали подход DB-first для генерации моделей в базовом приложении. NET. DataAnnotations были помещены в класс метаданных «приятель», чтобы избежать записи в автоматически сгенерированный файл. Когда контроллер вызывает TryValidateModel, все работает хорошо, требуется свойство Name.

public partial class User
{
    public string Name { get; set; }
}

[ModelMetadataType(typeof(UserMetaData))]
public partial class User : IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { }
}

public class UserMetaData
{
    [Required]
    public string Name { get; set; }
}

На служебном уровне приложения мы хотим реализовать дополнительную проверку, которая также проверяет, действительны ли объекты в отношении аннотаций данных. , Это делается с помощью Validator.TryValidateObject(), который успешно вызывает метод Validate, но игнорирует аннотации данных - пользователь действителен, даже с пустым именем.

TL; DR: MVC (веб-проект) знает, как считать данные аннотации, помещенные в «приятельский» класс с помощью атрибута ModelMetadataType, проект уровня службы - нет.

Я думал, что нашел ответ здесь , но, похоже, TypeDescriptor.AddProviderTransparent не работает для . net core apps.

Буду признателен за любые идеи.

1 Ответ

0 голосов
/ 17 марта 2020

Я действительно надеялся на однострочное решение:)

Я злоупотребил Ашрафами ответ на его собственный вопрос, например, так:

var metadataAttr = typeof(T).GetCustomAttributes(typeof(ModelMetadataTypeAttribute), true).OfType<ModelMetadataTypeAttribute>().FirstOrDefault();
if (metadataAttr != null)
{
    var metadataClassProperties = TypeDescriptor.GetProperties(metadataAttr.MetadataType).Cast<PropertyDescriptor>();
    var modelClassProperties = TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>();

    var errs =
        from metaProp in metadataClassProperties
        join modelProp in modelClassProperties
        on metaProp.Name equals modelProp.Name

        from attribute in metaProp.Attributes.OfType<ValidationAttribute>()
        where !attribute.IsValid(modelProp.GetValue(model))
        select new ValidationResult(attribute.FormatErrorMessage(Reflector.GetPropertyDisplayName<T>(metaProp.Name)), new[] { metaProp.Name });

    validationResults.AddRange(errs);
}
...