ModelState.IsValid против IValidateableObject в MVC3

Так по Гу IValidatableObject.Validate() должен вызываться, когда контроллер проверяет свою модель (т.е. до ModelState.IsValid) Однако, просто делая модель реализовать IValidatableObject не похоже на работу, потому что Validate(..) не вызывается.

Кто-нибудь знает, есть ли что-то еще, что я должен подключить, чтобы заставить это работать?

РЕДАКТИРОВАТЬ:

Вот код в соответствии с просьбой.

public class LoginModel : IValidatableObject
{
    [Required]
    [Description("Email Address")]
    public string Email { get; set; }

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

    [DisplayName("Remember Me")]
    public bool RememberMe { get; set; }

    public int UserPk { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var result = DataContext.Fetch( db => {

            var user = db.Users.FirstOrDefault(u => u.Email == Email);

            if (user == null) return new ValidationResult("That email address doesn't exist."); 
            if (user.Password != User.CreateHash(Password, user.Salt)) return new ValidationResult("The password supplied is incorrect.");

            UserPk = user.UserPk;
            return null;
        });

        return new List<ValidationResult>(){ result };
    }
}

Действие. (Я не делаю ничего особенного в контроллере...)

[HttpPost]
public ActionResult Login(LoginModel model)
{
    if (ModelState.IsValid)
    {
        FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
        return Redirect(Request.UrlReferrer.AbsolutePath);
    }

    if (ControllerContext.IsChildAction || Request.IsAjaxRequest())
        return View("LoginForm", model);

    return View(model);
}

Я установил точку останова на первой строке LoginModel.Validate() и это не похоже на удар.

2 ответа

Решение

Нет ничего более того, что вы просто должны добавить это к модели, которую вы проверяете. Вот пример проверки

public class User : IValidatableObject {
    public Int32 UserID { get; set; }
    public string Name { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        //do your validation

        return new List<ValidationResult>();
    }
}

И ваш контроллер будет использовать эту модель

public ActionResult Edit(User user) {
    if (ModelState.IsValid) {
    }
}

Надеюсь это поможет. Другими требованиями являются.net 4 и аннотации данных - которые вам, очевидно, нужны для ivalidatableobject. Опубликуйте какие-либо проблемы, и мы увидим, если мы не сможем их решить - например, опубликуем вашу модель и ваш контроллер... вы можете что-то упустить.

Проверка с использованием DefaultModelBinder является двухэтапным процессом. Первый, Data Annotations подтверждены. Тогда (и только если проверка аннотаций данных привела к нулевым ошибкам), IValidatableObject.Validate() называется. Все это происходит автоматически, когда у вашего поста есть параметр viewmodel. ModelState.IsValid ничего не делает как таковой. Скорее он просто сообщает, есть ли какой-либо элемент в ModelState коллекция имеет не пустой ModelErrorCollection,

Другие вопросы по тегам