I have a domain model and a view model as follows:
Domain Model:
namespace MvcApplication1.Models
{
public enum Sex { Male, Female };
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
[Required(ErrorMessage="Please select either Female or Male.")]
public Sex? Sex { get; set; }
}
}
View Model:
namespace MvcApplication1.ViewModels
{
public class HomeCreateVM
{
public HomeCreateVM()
{
}
public HomeCreateVM(Person p)
{
Person = p;
SelectList = p.Sex.GetSelectList();
}
public Person Person { get; set; }
public SelectList SelectList { get; set; }
}
}
The auxiliary extension method is defined as follows:
namespace MvcApplication1.Models
{
public static class Utilities
{
public static SelectList GetSelectList<XXX>(this XXX? obj) where XXX : struct
{
var values = from XXX x in Enum.GetValues(typeof(XXX))
select new { Text = x.ToString(), Value = x };
return new SelectList(values, "Value", "Text", obj);
}
}
}
Controller:
public ActionResult Create()
{
var p = new Person();
return View(new HomeCreateVM(p));
}
[HttpPost]
public ActionResult Create(Person hc)// the source of problem!
{
if (ModelState.IsValid)//always false!
{
TempData["status"] = hc;
return RedirectToAction("Confirm");
}
else
return View(new HomeCreateVM(hc));
}
HomeCreateVM.cshtml:
@model MvcApplication1.ViewModels.HomeCreateVM
<div>
Name: @Html.EditorFor(model => model.Person.Name)</div>
<div>
Sex: @Html.DropDownListFor(model => model.Person.Sex, Model.SelectList, "--Select--")</div>
Create View:
@model MvcApplication1.ViewModels.HomeCreateVM
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>HomeCreateVM</legend>
@Html.EditorForModel()
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Question:
There is no problem if the POST Create action method accepts a HomeCreateVM object as the argument.
However, if I change the POST Create action method argument from HomeCreateVM to Person (as shown in the code above), ModelState.IsValid always returns false.
The question is: “Is it possible to pass a ViewModel object to a Create view but only accept a DomainModel object from a POST Create action method?”
Because your view is strongly typed to the view model your form fields will look like this:
and if you want to bind correctly you need to specify the prefix: