Shaul Behr
Shaul Behr

Reputation: 38003

Why isn't custom validation working?

ASP.NET MVC3/Razor newbie question:

I am setting up a model with custom validation. While the properties that I decorate with things like [Required] and [RegularExpression(...)] are performing as expected, I'm finding that the custom validation is not working. I made my model implement IValidatableObject, and I can hit a breakpoint inside the Validate() method and watch the method doing a yield return new ValidationResult(...); - but the form nonetheless gets posted.

Is there some secret switch that I'm missing?

Upvotes: 1

Views: 222

Answers (2)

danludwig
danludwig

Reputation: 47375

The form will be posted when you use IValidatableObject to validate model properties. As Joeri Jans says, you can still prevent this and return the page to the user during your action method:

public ActionResult MyAction(MyModel model)
{
    if (ModelState.IsValid)
    {
        // code to perform action when input is valid
        return [return something]
    }
    return View(model); // re-display form because ModelState.IsValid == false
}

If you want your custom validation to prevent the form from being posted, you need to validate on the client. The easiest way to do this is with the RemoteAttribute.

public class MyModel
{
    [Remote("MyValidateAction", "MyController", HttpMethod = "POST")]
    public string MyProperty { get; set; }
}

You can still keep your code in IValidatableObject, and validate it from an action method like so:

[HttpPost]
public virtual JsonResult MyValidateAction(string myProperty)
{
    var model = new MyModel{ MyProperty = myProperty, };
    var results = new List<ValidationResult>();
    var isValid = Validator.TryValidateObject(model, 
        new ValidationContext(model, null, null), results, true);
    return isValid
        ? Json(true)
        : Json(results[0].ErrorMessage);
}

The above action method does virtually the same thing as the default model binder. It constructs an instance of your viewmodel, then validates it. All validation rules will be checked, including your IValidatableObject code. If you need to send more properties to the action method for the construction of your viewmodel, you can do so with the AdditionalFields property of the RemoteAttribute.

Hope this helps.

Upvotes: 1

JoJa
JoJa

Reputation: 610

If you are talking about server side validation, do you have the ModelState.Isvalid check? http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

Upvotes: 2

Related Questions