views:

40

answers:

1

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);
}
A: 

Have you tried to fill in all other fields so all the out-of-the-box validation are satisfied, and see if your custom validation is triggered? If the client validation are not satisfied, the form will be prevented from posting back and thus your server-side custom validation will not be trigerred,

To have your custom validation attribute work on the client side, some additional work has to be made.

Read up on Phil's excellent post on validation here: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx

Bill Yang
At the moment I'm not doing client side validation to try and get this to work. At least I don't think I am. Hmm I should maybe check that. However, I was running break points on the ModelState.IsValid in the controller and the Model's error collection never had error states for my custom validation items. And yes, before my update, I filled out the form and it still didn't trigger the custom validation attribute. :(
Jack
hmm, so my assumption was wrong, and this is truely strange. Can you post code for you [HttpGet] method and the view?
Bill Yang