CompareAttribute и сравнение со свойствами сложного типа - PullRequest
2 голосов
/ 08 марта 2011

Я только что прочитал о новом атрибуте CompareAttribute MVC3, который можно применить к свойству модели, чтобы определить другое свойство, которому оно должно соответствовать - классический вариант использования - подтверждение правильности введенного адреса электронной почты или наличие полей Password и ConfirmPassword.Я столкнулся с проблемой при попытке реализовать его в своем собственном проекте.

У нас есть довольно стандартный объект User, который, помимо прочего, имеет следующие свойства:

public class User {
    ....
    [Required, RegularExpression(RegularExpressions.Email, ErrorMessage = "Please supply a valid email address")]
    public string EmailAddress

    [Required]
    public string Password
    ....
}

Затем я включил User и несколько других необходимых нам объектов в модель представления:

public class SignUpViewModel {
   ....
   public User user { get; set; }
   ....
}

, которая при передаче в форму в пользовательском интерфейсе позволяет ModelBinder запускать проверку аннотации данныхдля объекта User, а также других объектов и типов примитивов в SignUpViewModel, когда пользователь отправляет форму.Я был очень рад, когда все это «просто сработало», потому что это означало, что мы можем определить валидацию только в одном месте и не иметь слишком много работы для сохранения в базе данных или сопоставления моделей пользовательского интерфейса с моделями доменов и т. Д.

Заметив, что Html.EditorFor (model => model.User.Password) испускает объект с именем, установленным в «User.Password», я добавил в SignUpViewModel следующее:

[Required, Compare("User.Password")]
public string ConfirmPassword { get; set; }

, но отправивФорма теперь вызывает ошибку проверки в соответствии с «Не удалось найти свойство с именем User.Password».Я надеялся, что он будет следовать соглашению такого же рода, но, похоже, не будет: (

Я действительно не хочу помещать ConfirmPassword в объект User, так как ConfirmPassword является чисто пользовательским интерфейсом, и кажется,неправильно иметь такое в доменном объекте, подобном этому. Я также не очень хочу сгладить различные объекты в SignUpViewModel, поскольку это начинает казаться дублированием того, где определены правила проверки, и мы пытаемся сохранить наш код какСУХОЙ, насколько это возможно.

Кто-нибудь сталкивался с способом заставить CompareAttribute работать со сравнением со свойствами одноуровневых объектов, а не со свойствами одноуровневого элемента, как это может показаться для атрибута?

Ответы [ 3 ]

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

Избавьтесь от свойства User на вашем SignUpViewModel и поместите необходимые свойства от объекта домена User на SignUpViewModel.

Вы сказали, что хотите, чтобы ваши проблемы были разделены, и наличие объекта домена в качестве свойства в модели представления является примером того, как ваши проблемы не были разделены.

Может показаться, что это может привести к написанию большего количества кода, но посмотрите на решение, подобное Automapper , чтобы автоматизировать сопоставление свойств вашего доменного объекта для просмотра свойств модели.

1 голос
/ 20 февраля 2012

Несмотря на то, что ответ smartcaveman велик с архитектурной точки зрения, он не решает первоначальный вопрос о невозможности использовать клиентскую проверку CompareAttribute в MVC3 внутри моделей, содержащихся в некоторой родительской модели (сложной модели).Мне известна ситуация, когда некоторую многократно используемую [под] модель можно повторно использовать из нескольких моделей родительских контейнеров, а CompareAttribute используется внутри подмодели.Проверка на стороне сервера в MVC3 будет работать нормально (когда на клиенте отключен javascript), но есть ошибка в javascript, предоставленная Microsoft, которая нарушает проверку на стороне клиента.Пожалуйста, перейдите по ссылке ниже для разрешения:

MVC3 CompareAttribute Ошибка на стороне клиента (stackoverflow)

0 голосов
/ 21 сентября 2016

Я недавно столкнулся с этой проблемой сам;вот как я это решил.

[Compare("OriginalPassword")]
public string ConfirmPassword { get; set; }

public string OriginalPassword
{
    get
    {
        return User.Password;
    }
}
...