Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Data Annotations IsValid is never invoked. (ASP.NET MVC 2 .NET 4)

I have a custom Data Validation Attribute I've created to make sure the passwords a user inputs are the same, but IsValid is never invoked.

Custom attribute:

public class IsSameAsAttribute : ValidationAttribute
{
    public String TargetProperty { get; set; }
    private readonly object _typeId = new object();

    public IsSameAsAttribute(string targetProperty)
    {
        TargetProperty = targetProperty;
    }

    public override bool IsValid(object value)
    {
        return false;
        //Type objectType = value.GetType();
        //bool isValid = false;

        //PropertyInfo[] neededProperties =
        //    objectType.GetProperties().Where(propertyInfo => propertyInfo.Name == TargetProperty).ToArray();

        //return isValid;
    }

    public override object TypeId
    {
        get { return _typeId; }
    }
}

Data model it is applied to:

public class RegistrationData
{
    [Required(ErrorMessage = "First Name Required")]
    [StringLength(100, ErrorMessage = "First Name must be 100 characters or less.")]
    public String FirstName { get; set;}

    [Required(ErrorMessage = "Last Name Required")]
    [StringLength(100, ErrorMessage = "Last Name must be 100 characters or less.")]
    public String LastName { get; set; }

    [Required(ErrorMessage = "Email is Required")]
    [StringLength(200, ErrorMessage = "Email must be 200 characters or less.")]
    [RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Valid Email Address is required.")]
    public String Email { get; set; }

    [Required(ErrorMessage = "Password is required")]
    public String Password { get; set; }

    [IsSameAs("Password")]
    public String PasswordRepeat { get; set; }

    [Required(ErrorMessage = "Division is required")]
    public String Division { get; set; }

}

And the Controller where it is called from:

[HttpPost]
public ActionResult ValidationDemo(RegistrationData model)
{
    if (ModelState.IsValid)
    {
        return Redirect("/");
    }

    return View(model);
}

All the "out of the box" validations operate correctly, it is just my custom one that isn't being invoked. In doing debugging I find that it is instantiated as the constructor is called, but a break-point set on IsValid is never hit.

What is going on and how do I fix it?

UPDATE

All right I fiddled some and if I call TryUpdateModel(model) in my controller it finally invokes IsValid. So this implies to me that my custom attribute isn't getting "registered" with whatever runs the validations in MVC 2. Is there a way to address this?

[HttpPost]
public ActionResult ValidationDemo(RegistrationData model)
{
    TryValidateModel(model);  // <--- *** Added this line and it "works"

    if (ModelState.IsValid)
    {
        return Redirect("/");
    }

    return View(model);
}
like image 348
Jack Avatar asked Jun 29 '10 21:06

Jack


1 Answers

I'm seeing a similar/same/related issue with MVC2 - the class-level validation is called only if all the properties validate correctly.

So multiple properties may fail, and all validation messages are added to the model state (and displayed on the client.) But the class-level validation message isn't among them; the IsValid on these only gets called if properties pass. Bit a a bummer from a usability standpoint but it works.

I am not calling TryValidateModel().

like image 113
Jim Avatar answered Oct 20 '22 18:10

Jim