views:

81

answers:

1

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("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 };
    }
}

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.

+2  A: 

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.

BuildStarted
You are correct, the one caveat is that if you have any validation attributes that result in the model being invalid, Validate never gets called. That was my issue.
Master Morality
Ah, how interesting. Thanks for that.
BuildStarted