Проверка уровня класса/модели (в отличие от уровня собственности)? (ASP.NET MVC 2.0)
В принципе, что говорится в названии. У меня есть несколько свойств, которые объединяются, чтобы действительно сделать один логический ответ, и я хотел бы запустить код проверки на стороне сервера (который я пишу), который учитывает эти несколько полей и подключается к одному сообщению вывода/ошибки проверки, которое пользователи видят на веб-странице.
Я рассмотрел способ распространения атрибута scott guthries и использования его в ваших объявлениях dataannotations, но, как я вижу, не существует способа объявить атрибут атрибута dataannotations для нескольких свойств, и вы можете разместить объявления только (например, [Email], [Range], [Required]) над одним свойством: (.
Я просмотрел PropertyMustMatchAttribute в проекте mvc 2.0 по умолчанию, который появляется при запуске нового проекта, этот пример так же полезен, как использование пары контактов для проверки вашего моторного масла - бесполезно!
Я попробовал этот метод, однако, создав атрибут уровня класса, и не знаю, как отобразить ошибку из этого на моей странице aspx. Я пробовал html.ValidationMessage( "ClassNameWhereAttributeIsAdded" ) и множество других вещей, и он не сработал. и я должен упомянуть, что на этом уровне нет публикации в блоге, несмотря на то, что это является общей потребностью в любом сценарии проекта или бизнес-логики!
может ли кто-нибудь помочь мне в том, чтобы мое сообщение отображалось на моей странице aspx, а также, если возможно, правильный документ или ссылку, объясняющие валидацию на этом уровне?
Ответы
Ответ 1
Теперь, когда вы просмотрели аннотации данных и пришли к выводу, что они не адаптированы к вашему сценарию, я бы предложил вам посмотреть FluentValidation, его интеграция с ASP.NET MVC и то, как вы unit test ваша логика проверки - вы не будете разочарованы (я действительно ничего не имею против аннотаций Данных, они отлично подходят для сообщений в блогах и учебных пособий, но как только вы сталкиваетесь с приложениями реального мира, вы быстро понимаете границы).
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");
}
}
Ответ 2
Я не уверен, но вы тот, кто не дает никаких ответов на мои ответы/вопросы без видимой причины (или b/c моих просмотров на 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
для выполнения общей задачи. Я попытался разбить код, чтобы сделать его более понятным/понятным.
Ответ 3
Возможный Dupe:
Написание атрибута CompareTo DataAnnotation
Ответы на ваши вопросы должны быть там и, по крайней мере, указывают на это сообщение в блоге:
http://byatool.com/mvc/custom-data-annotations-with-mvc-how-to-check-multiple-properties-at-one-time/
Чтобы отобразить сообщение об ошибке, вы должны использовать:
<%: Html.ValidationMessage("") %>
Что происходит, так это то, что вы проверяете на уровне класса, что вы получаете ModelState с ключом, обычно называемым именем свойства, с пустой строкой.
Ответ 4
При создании атрибута уровня класса путем подкласса из ValidationAttribute, если проверка не выполняется, в ModelState = > не будет соответствующего ключа, это будет пустая строка, но в приведенной ниже ссылке предоставляется ссылка, которая поможет U отобразить сообщение об ошибке в ur View
используя только html.ValidationMessage( "urpropertyname" ) вместо того, что U пробовал html.ValidationMessage( "ClassNameWhereAttributeIsAdded" ).
Невозможно установить членские имена из настраиваемого атрибута проверки в MVC2
Ответ 5
Я знаю, что на это уже был дан ответ, но похоже, что MVC3 добавил другой способ выполнить это, если вы хотите продолжить использование атрибутов DataAnotations.
Ваш класс может реализовать интерфейс IValidatableObject, который предоставляет метод Validate. Еще один способ обмануть кошку.
Ответ 6
Я сделал следующее, используя 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, список продолжает расти.
уверен, что команда продолжает давать эти "крутые" примеры того, как простые вещи используют воображаемые примеры не-реального мира, и когда дело доходит до реальных вещей, это похоже на "черт возьми, мы не знаем или не заботимся, и не будем рассказывать вам о это, вам просто нужно столкнуться с этим и разобраться в себе" тип сделки
oh, и обновление нескольких частей представления в одном раунде еще не возможно, если вы не используете js-хак и не обрезаете возвращаемый html и не назначаете его другим div... вы даже не можете возвращать несколько просмотров или по крайней мере, обновить несколько областей страницы изначально (в одном кругосветном путешествии), ее просто опечалить.
Возможно, когда MVC достигнет версии 3.0, она может быть полной, скрестив пальцы, поскольку инфраструктура dotnet не была реалистично "полной" до clr 3.5 и в том числе linq/EF для SQL...