Search code examples
jqueryasp.netasp.net-mvcasp.net-mvc-3unobtrusive-validation

Why does my partial view validate on page load?


I'm using asp.net MVC3 and client-side validation in order to help validate my form. This works brilliantly, but I have however encountered an unusual situation. Part of my form (2 inputs, to be exact) is loaded from a partial view. These fields have their own validation rules (such as 'required') and work as expected. Well, almost. The strange thing is the fact that the rules seem to run as soon as the partial view is 'requested' on page load. So I'll have around 20 form fields or so; with 2 of which (from the partial view) stating 'This field is required'.

Here is my parent page calling the partial view:

@Html.Action("Index", "Foo", @Model.Foo)

Setting the property in my partial view's model:

[Required(ErrorMessage = "This is required.")]
public string foo { get; set; }

Displaying the inputs and validation in my partial view's View:

@Html.LabelFor(m => m.test, "Test")
@Html.TextBoxFor(m => m.test)
@Html.ValidationMessageFor(m => m.test)

Calling the partial view from its Controller:

public ActionResult Index(Foo myModel)
{
    return PartialView("_PartialView", myModel);
}

Does anybody know what could be causing this? If not, are there any ways in which I can debug this validation to find out what's going on?


Solution

  • The reason this happens is because when the default model binder tries to parse the myModel argument of the Index action from the request values it automatically add errors to the ModelState. And I suspect that the Model.Foo that you are passing is invalid.

    One possibility is to clear the model state if you want:

    public ActionResult Index(Foo myModel)
    {
        ModelState.Clear();
        return PartialView("_PartialView", myModel);
    }
    

    Another possibility is to pass a Foo instance that is valid (i.e. the test property must have a value). In fact if you don't want to pass any values you don't really need this action argument and you could have the action like this:

    public ActionResult Index()
    {
        var myModel = new Foo();
        return PartialView("_PartialView", myModel);
    }
    

    and now because there is no action argument the default model binder doesn't try to parse it and it won't add model errors.