модель mvc и модель просмотра?

Итак, у меня есть модель «Пользователь», в которой много полей, но следующие из них:


public int Id {get;set;}
public string Username { get; set; }
public string Pwd { get; set; }

и у меня есть модель представления, которая проверяет пароль, который я использую на другом контроллере:

public class ConfirmPassword : IValidatableObject
{
    [Required]
    public string Password { get; set; }
    [Required(ErrorMessage="Confirm Password field is required.")]
    public string ConfirmPwd { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        string regex1 = @"^.{8,10}$";                   // 8 - 10 characters

        Match requirement1 = Regex.Match(Password, regex1);

        if (Password != ConfirmPwd)
            yield return new ValidationResult("Password and Confirm Password is not identical.");

        if (!requirement1.Success)
            yield return new ValidationResult("Password must be between 8 and 10 characters.");


    }
}

есть ли способ, где я могу подключить модель представления к моей модели? или просто скопировать и вставить коды мой единственный вариант? Я не могу скопировать и вставить, так как код должен иметь IValidateObject, который испортит всю сущность пользователя, поскольку происходит множество фоновых проверок. Мне просто нужно проверять пароли всякий раз, когда профиль редактируется/создается.

РЕДАКТИРОВАТЬ: извините, если все запутались. в основном, у меня есть несколько проверок, которые мне нужны для подтверждения паролей, которые не могут быть обработаны аннотациями данных, поэтому модель просмотра подтверждения пароля. эту проверку я хочу применить к модели пользователя, но без добавления в нее поля «ConfirmPassword». так как мне не нужно другое поле в базе данных. Мой вопрос заключается в том, как заставить проверки, которые у меня есть из подтверждения пароля, срабатывать всякий раз, когда представление POST и поле пароля не соответствуют его требованиям?

namespace
{
    public class User 
    {
public int Id {get;set;}
public string Username { get; set; }
public string Pwd { get; set; }

    }
}


namespace
{
    public class ConfirmPassword : IValidatableObject
    {
        [Required]
        public string Password { get; set; }
        [Required(ErrorMessage="Confirm Password field is required.")]
        public string ConfirmPwd { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            string regex1 = @"^.{8,10}$";                   // 8 - 10 characters
            string regex2 = @"(?:.*?[A-Z]){1}";             // 1 uppercase
            string regex3 = "";             // 1 lowercase
            string regex4 = "";                // 1 numeric

            Match requirement1 = Regex.Match(Password, regex1);
            Match requirement2 = Regex.Match(Password, regex2);
            Match requirement3 = Regex.Match(Password, regex3);
            Match requirement4 = Regex.Match(Password, regex4);

            if (Password != ConfirmPwd)
                yield return new ValidationResult("Password and Confirm Password is not identical.");

            if (!requirement1.Success)
                yield return new ValidationResult("Password must be between 8 and 10 characters.");

            if (!requirement2.Success)
                yield return new ValidationResult("Password must contain at least 1 uppercase letter.");

            if (!requirement3.Success)
                yield return new ValidationResult("Password must contain at least 1 lowercase letter.");

            if (!requirement4.Success)
                yield return new ValidationResult("Password must contain at least 1 numeric character.");

        }
    }
} 

person gdubs    schedule 28.06.2011    source источник
comment
почему бы тебе не использовать StringLengthAttribute   -  person Daniel A. White    schedule 28.06.2011
comment
ну, это не единственные проверки, которые у меня есть. я просто сократил его. есть еще 4, которые используют регулярное выражение.   -  person gdubs    schedule 28.06.2011
comment
Если вы хоть как-то контролируете ситуацию, вам следует избегать использования установленного верхнего предела длины паролей. Сообщение внешнему миру, что пароли состоят из 8-10 символов, также сообщает хакерам, сколько символов использовать при атаке методом грубой силы.   -  person Ed Charbeneau    schedule 28.06.2011
comment
хорошо, это не используется для входа в систему, у меня есть отдельная модель просмотра, которая проверяет входы в систему. это необходимо только для регистрации, которая будет иметь еще один уровень безопасности, прежде чем пользователь попадет сюда.   -  person gdubs    schedule 28.06.2011


Ответы (5)


Вы можете использовать шаблон декоратора в своей модели представления, чтобы делать то, что вам нравится. Вы также можете использовать атрибуты пространства имен System.ComponentModel.DataAnnotations, чтобы выполнить всю проверку за вас.

public class ConfirmPassword 
{
    User model;

    [Required]
    public string Username 
    { 
        get { return this.model.Username; } 
        set { this.model.Username = value; } 
    }
    [Required]
    [DataType(DataType.Password)]
    public string Password 
    { 
        get { return this.model.Pwd; } 
        set { this.model.Pwd = value; } 
    }

    [Required(ErrorMessage = "Confirm Password field is required.")]
    [Compare("NewPassword", 
       ErrorMessage = "The new password and confirmation password do not match.")]
    [RegularExpression(@"^.{8,10}$")]
    [DataType(DataType.Password)]
    public string ConfirmPwd { get; set; }

    public ConfirmPassword()
    {
        this.model = new User();
    }

    public ConfirmPassword(User model)
    {
        this.model = model;
    }

}
person Jay    schedule 28.06.2011

Хорошо, я все еще немного сомневаюсь в том, что вы подразумеваете под подключением модели представления к объекту модели... Я думаю, что вы хотите теперь проверить, соответствует ли пароль от фактического пользователя паролю, переданному в модель представления.

Лично я бы не делал этого в самой модели представления, а скорее в контроллере и добавлял бы ModelState.AddError, если пароль был неверным.

Обычная проверка ввода может происходить на стороне сервера или клиента, если вы используете проверку на стороне клиента, но вы не можете проверить пароль на стороне клиента, поэтому он должен будет перейти на сервер.

public LoginViewModel()
{
  [Required]
  public string LoginId {get; set;}

  [DataType(DataType.Password)]
  public string Password {get; set;}

  [DataType(DataType.Password)]
  public string ConfirmPassword {get; set;}

 // this validation is not db related and can be done client side...
 public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        string regex1 = @"^.{8,10}$";                   // 8 - 10 characters

        Match requirement1 = Regex.Match(Password, regex1);

        if (Password != ConfirmPwd)
            yield return new ValidationResult("Password and Confirm Password is not identical.");

        if (!requirement1.Success)
            yield return new ValidationResult("Password must be between 8 and 10 characters.");


    }

}

[HttpGet]
public ActionResult Login()
{
   var model = new LoginViewModel();

   return View("Login",model);
}

[HttpPost]
public ActionResult Login(LoginViewModel model)
{

   var user = GetUserFromRepositoryByUsername(model.username);

   if(user != null)
    {
      if(user.password == model.Password)
      {
        RedirectToAction("YouLoggedInYay!");
      }
    }

    // if we made it this far, the user didn't exist or the password was wrong.
    // Highlight the username field red and add a validation error message.
    ModelState.AddError("Username","Your credentials were invalid punk!");

   return View("Login",model);
}
person David C    schedule 28.06.2011

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

После проверки комбинации паролей вы используете идентификатор для получения соответствующего пользователя и обновляете его новым паролем. Вы можете просто сделать это в рамках действия публикации нового пароля.

Кстати, вы можете сопоставить старый пароль.

person Community    schedule 28.06.2011

Из того, что я считаю, ваши проверки пользовательского интерфейса и проверки логики не следует смешивать. Это стоит повторить в Логике, даже если это одно и то же. По сути, объект Entity не несет ответственности за выполнение проверок. Это может быть какой-то класс сервисного уровня, который делает это для Entity. И вы, вероятно, можете создать исключение в этот момент. Таким образом, оно обрабатывается совершенно по-разному в пользовательском интерфейсе и логике.

person Illuminati    schedule 28.06.2011

«Мне просто нужно проверять пароли всякий раз, когда профиль редактируется/создается»

Используйте аннотации данных в сочетании с IsValid в ViewModel для проверки ошибок. Что касается сопоставления модели с моделью представления, просто используйте шаблон декоратора.

Используйте System.ComponentModel.DataAnnotations (у них даже есть валидатор регулярных выражений, который вы можете использовать). После того, как пароли проверены на соответствие политике, преобразуйте их в хэш MD5 и сохраните его, а не значение пароля. Если ничего не помогает, нет ничего плохого в создании отдельный класс UserValidation и разделяйте логику между моделью представления и моделью, например. они оба вызывают одни и те же методы для определения достоверности (сокращение кода).

person Pepto    schedule 28.06.2011