MVC3 中的 ModelState.IsValid 与 IValidateableObject

发布于 2024-09-19 21:56:34 字数 1880 浏览 3 评论 0原文

所以根据 Gu 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() 的第一行设置了一个断点,它似乎没有被击中。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

灼疼热情 2024-09-26 21:57:11

使用 DefaultModelBinder 进行验证是一个两阶段的过程。首先,验证数据注释。然后(并且仅当数据注释验证导致零错误时),调用 IValidatableObject.Validate()。当您的后期操作具有视图模型参数时,这一切都会自动发生。 ModelState.IsValid 不会执行任何此类操作。相反,它只是报告 ModelState 集合中的任何项目是否具有非空 ModelErrorCollection

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.

邮友 2024-09-26 21:57:00

您只需将其添加到您正在验证的模型中即可。这是一个验证示例

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。发布任何问题,我们会看看是否无法解决它们 - 例如发布您的模型和控制器......您可能会丢失一些东西。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文