Проверка уровня класса / модели (в отличие от уровня свойства) (ASP.NET MVC 2.0) - PullRequest
15 голосов
/ 06 мая 2010

В основном то, что говорит название. У меня есть несколько свойств, которые объединяются, чтобы действительно получить один логический ответ, и я хотел бы запустить код проверки на стороне сервера (который я пишу), который учитывает эти несколько полей и подключает только одно сообщение проверки / сообщение об ошибке, которое пользователи видят на веб-странице.

Я посмотрел на метод Скотта Гатриса по расширению атрибута и использованию его в ваших объявлениях dataannotations, но, как я могу видеть, нет способа объявить атрибут стиля dataannotations для нескольких свойств, и вы можете только разместить объявления (например, [Email], [Range], [Required]) для одного свойства: (.

Я посмотрел на PropertiesMustMatchAttribute в проекте mvc 2.0 по умолчанию, который появляется при запуске нового проекта, этот пример так же полезен, как использование пары выводов для проверки моторного масла - бесполезно!

Я попробовал этот метод, однако, создав атрибут уровня класса, и не знаю, как отобразить ошибку из этого на моей странице aspx. Я пробовал html.ValidationMessage ("ClassNameWhereAttributeIsAdded") и множество других вещей, и это не сработало. и я должен упомянуть, что на этом уровне нет ОДНОГО сообщения в блоге о проведении валидации - несмотря на то, что это является общей потребностью в любом проекте или сценарии бизнес-логики!

Может ли кто-нибудь помочь мне с отображением моего сообщения на моей странице aspx, а также, если возможно, с соответствующим документом или справкой, объясняющей валидацию на этом уровне?

Ответы [ 6 ]

14 голосов
/ 06 мая 2010

Теперь, когда вы посмотрели аннотации данных и пришли к выводу, что они не адаптированы к вашему сценарию, я бы посоветовал вам взглянуть на FluentValidation , его интеграция с ASP.NET MVC и то, как вы будете модульно тестировать свою логику проверки - вы не будете разочарованы (я действительно ничего не имею против аннотаций данных, они отлично подходят для постов в блогах и учебных пособий, но как только вы столкнетесь с реальным миром приложения вы быстро осознаете ограничения).


UPDATE:

В соответствии с запросом в разделе комментариев приведен пример использования платформы FluentValidation с одной функцией проверки на стороне сервера, которая обращается к нескольким свойствам (не делайте этого, так как это уродливо и есть лучший способ):

class AuthInfo
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
}

class AuthInfoValidator : AbstractValidator<AuthInfo>
{
    public override ValidationResult Validate(AuthInfo instance)
    {
        var result = base.Validate(instance);
        if (string.IsNullOrEmpty(instance.Username))
        {
            result.Errors.Add(new ValidationFailure("Username", "Username is required"));
        }
        if (string.IsNullOrEmpty(instance.Password))
        {
            result.Errors.Add(new ValidationFailure("Password", "Password is required"));
        }
        if (string.IsNullOrEmpty(instance.ConfirmPassword))
        {
            result.Errors.Add(new ValidationFailure("ConfirmPassword", "ConfirmPassword is required"));
        }
        if (instance.Password != instance.ConfirmPassword)
        {
            result.Errors.Add(new ValidationFailure("ConfirmPassword", "Passwords must match"));
        }
        return result;
    }
}

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

class AuthInfoValidator : AbstractValidator<AuthInfo>
{
    public AuthInfoValidator()
    {
        RuleFor(x => x.Username)
            .NotEmpty()
            .WithMessage("Username is required");

        RuleFor(x => x.Password)
            .NotEmpty()
            .WithMessage("Password is required");

        RuleFor(x => x.ConfirmPassword)
            .NotEmpty()
            .WithMessage("ConfirmPassword is required");

        RuleFor(x => x.ConfirmPassword)
            .Equal(x => x.Password)
            .WithMessage("Passwords must match");
    }
}
3 голосов
/ 07 мая 2010

Возможен Дупе:

Запись атрибута аннотирования данных сравнения

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

http://byatool.com/mvc/custom-data-annotations-with-mvc-how-to-check-multiple-properties-at-one-time/


Чтобы отобразить сообщение об ошибке, вы должны использовать:

<%: Html.ValidationMessage("") %>

Что происходит, потому что вы проверяете на уровне класса, получаете ли ModelState с ключом, обычно именем свойства, с пустой строкой.

3 голосов
/ 07 мая 2010

Я не уверен, но вы тот, кто продолжает голосовать за мои ответы / вопросы без видимой причины (или из моих взглядов на VB.NET)?

В любом случае, PropertiesMustMatchAttribute - это просто хорошая реализация использования значений определенного свойства объекта. Если вам нужно запустить некоторую логику, используя несколько полей объекта, вы можете сделать это следующим образом, аналогично тому, что делает PropertiesMustMatchAttribute.

Ниже будет основная часть ValidationAttribute, которая обращается к свойствам объекта для запуска некоторой логики.

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);

        // Get the values of the properties we need. 
        // Alternatively, we don't need to hard code the property names,
        // and instead define them via the attribute constructor
        object prop1Value = properties.Find("Person", true).GetValue(value);
        object prop2Value = properties.Find("City", true).GetValue(value);
        object prop3Value = properties.Find("Country", true).GetValue(value);

        // We can cast the values we received to anything
        Person person = (Person)prop1value; 
        City city = (City)prop2value;
        Country country = (Country)prop3value;

        // Now we can manipulate the values, running any type of logic tests on them
        if(person.Name.Equals("Baddie") && city.ZIP == 123456)
        {
            return country.name.Equals("Australia");
        }
        else
        {
            return false;
        }         
    }

PropertiesMustMatchAttribute просто использует Reflection для выполнения общей задачи. Я попытался разбить код, чтобы сделать его более читаемым / более легким для понимания.

2 голосов
/ 08 марта 2012

Я знаю, что на этот вопрос уже дан ответ, но, похоже, MVC3 добавил еще один способ сделать это, если вы хотите продолжать использовать атрибуты DataAnotations.

Ваш класс может реализовать интерфейс IValidatableObject, который предоставляет метод Validate. Просто еще один способ снять кожу с кошки.

2 голосов
/ 03 января 2012

При создании атрибута уровня класса подклассом из ValidationAttribute, если проверка не пройдена, в ModelState нет соответствующего ключа => это будет пустая строка, но в приведенной ниже ссылке предусмотрен обходной путь, который поможет U отобразитьсообщение об ошибке в ur View, используя только html.ValidationMessage ("urpropertyname") вместо того, что U пробовал html.ValidationMessage ("ClassNameWhereAttributeIsAdded").

Невозможно установить имена членов из пользовательского атрибута проверки вMVC2

1 голос
/ 11 мая 2010

Я сделал следующее, используя FluentValidator, если это кому-нибудь полезно, благодаря рекомендациям Дарина:

Public Class tProductValidator
Inherits AbstractValidator(Of tProduct)


Public Sub New()
    Const RetailWholsaleError As String = "You need to enter either a Retail Price (final price to user) or a Wholesale Price (price sold to us), but not both."
    Dim CustomValidation As System.Func(Of tProduct, ValidationFailure) =
     Function(x)
         If (x.RetailPrice Is Nothing AndAlso x.WholesalePrice Is Nothing) OrElse (x.RetailPrice IsNot Nothing AndAlso x.WholesalePrice IsNot Nothing) Then
             Return New ValidationFailure("RetailPrice", RetailWholsaleError)
         End If
         Return Nothing
     End Function

    Custom(CustomValidation)
End Sub

End Class

как обычно, я был одурачен, полагая, что MVC - это полноценная среда, в которой возможны сценарии реального мира. как же они публикуют такие вещи и даже не упоминают об их ограничениях, я не понимаю, мы, разработчики, затем сталкиваемся с проблемами, которые являются кошмаром, или нам приходится полагаться на сторонние материалы, чтобы выполнить то, что по своей сути является обязанностью MVC, а если сторонние предметы не были доступны - тогда что?

это не первое серьезное отступление, которое я обнаружил в mvc 2.0, список продолжает расти.

уверен, что команда продолжает приводить эти «классные» примеры того, как простые вещи используют воображаемые примеры не-реального мира, и когда дело доходит до реальных вещей, это похоже на «черт, нам это не важно, и мы не будем рассказывать вам о них». это, вам просто нужно наткнуться на это и разобраться с этим самостоятельно "тип сделки

о, и обновление нескольких частей представления в одном цикле все еще невозможно, если вы не воспользуетесь хаком js, не разрежете HTML-код возврата и не назначите его разным элементам div ... вы даже не сможете вернуть несколько представлений или обновить хотя бы несколько областей страницы (за один раз), это просто печально.

Может быть, когда MVC достигнет версии 3.0, она может быть фактически завершена, скрестив пальцы, так как структура dotnet не была реалистично «завершена» до версии 3.5, включая linq / EF to SQL ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...