so according to Gu IValidatableObject.Validate()
should get called when a controller validates it's model (i.e. before ModelState.IsValid
) however simply making the model implement IValidatableObject
doesn't seem to work, because Validate(..)
doesn't get called.
Anyone know if there is something else I have to wire up to get this to work?
EDIT:
Here is the code as requested.
public class LoginModel : IValidatableObject
{
[Required]
[Description("E开发者_运维问答mail 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 };
}
}
The action. ( I don't do anything special in the Controller...)
[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);
}
I set a break point on the first line of LoginModel.Validate()
and it doesn't seem to get hit.
There isn't anything more than that you just have to add it to the model you're validating. Here's an example of validation
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>();
}
}
And your controller would use this model
public ActionResult Edit(User user) {
if (ModelState.IsValid) {
}
}
Hope this helps. Other requirements are .net 4 and data annotations - which you obviously need jsut for ivalidatableobject. Post any issues and we'll see if we can't resolve them - like post your model and your controller...you might be missing something.
Validation using the DefaultModelBinder is a two stage process. First, Data Annotations
are validated. Then (and only if the data annotations validation resulted in zero errors), IValidatableObject.Validate()
is called. This all takes place automatically when your post action has a viewmodel parameter. ModelState.IsValid
doesn't do anything as such. Rather it just reports whether any item in the ModelState
collection has non-empty ModelErrorCollection
.
精彩评论