I'm running into a problem with the ModelState already having errors when getting a PartialView using @Html.Action()
.
I have the following controller:
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
public class TestController : Controller
{
private readonly object[] items = {new {Id = 1, Key = "Olives"}, new {Id = 2, Key = "Tomatoes"}};
[HttpGet]
public ActionResult Add()
{
var model = new ViewModel {List = new SelectList(items, "Id", "Key")};
return View(model);
}
public ActionResult _AddForm(ViewModel viewModel)
{
var errors = ModelState.Where(m => m.Value.Errors.Count > 0).ToArray();
return PartialView(viewModel);
}
}
And the following ViewModel:
public class ViewModel
{
[Required]
public int? SelectedValue { get; set; }
public SelectList List { get; set; }
}
The Add view looks like this:
@model ViewModel
<h1>Add a thing to a list</h1>
@using (Html.BeginForm())
{
@Html.ValidationSummary()
@Html.Action("_AddForm", Model)
<button class="btn btn-success">Submit</button>
}
Finally the _AddForm PartialView looks like this:
@model ViewModel
<div class="form-group">
@Html.ValidationMessageFor(m => m.SelectedValue)
@Html.LabelFor(m => m.SelectedValue, "Please select a thing:")
@Html.DropDownListFor(m => m.SelectedValue, Model.List, new {@class = "form-control"})
</div>
When this page loads the ModelState already has an error in the PartialView because the SelectedValue is required.
I don't understand why this happens, surely the _AddForm action is a HTTP GET and does not cause model state validation?
(Note, I don't want to use @Html.Partial()
because I need to do some logic in the Action.)
The reason this occurs is that passing the strongly typed ViewModel as a parameter to the action causes the model binding and validation to occur again.
There seems to be no way to avoid this re-validation.
I originally attempted to use the Action as a way to get around the way MVC seemed to be caching some information about my ViewModel when using
Html.Partial()
.This "caching" turned out to be in the ModelState: https://stackoverflow.com/a/7449628/1775471