I have a Create view which is passed a ViewModel. The ViewModel contains the following:
namespace MyProject.ViewModels
{
public class MyObjectCreateView
{
public MyObject MyObject { get; set; }
public List<OtherObject> OtherObjects { get; set; }
}
}
The objects are generated using Entity Framework. I have a metadata partial class for MyObject:
[MetadataType(typeof(MyObjectMetaData))]
public partial class MyObject
{
// Validation rules for the MyObject class
public class MyObjectMetaData
{
// Validation rules for MyObjectId
[DisplayName("MyObject")]
[Required(ErrorMessage = "Please enter the MyObject ID number.")]
[DisplayFormat( ApplyFormatInEditMode=true,
ConvertEmptyStringToNull=true,
HtmlEncode=true)]
[DataType(DataType.Text)]
[StringLength(25, ErrorMessage = "Must be under 25 characters.")]
public object MyObjectId { get; set; }
// Validation rules for Title
[Required(ErrorMessage = "Please enter the Title for MyObject.")]
[DataType(DataType.MultilineText)]
[StringLength(200, ErrorMessage = "Must be under 200 characters.")]
[DisplayFormat(ApplyFormatInEditMode = true,
ConvertEmptyStringToNull = true,
HtmlEncode = true)]
public object Title { get; set; }
Etc...
My Create view looks like this:
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<%:Html.ValidationSummary(true, "Please fix the following errors:") %>
<%:Html.EditorFor(model => model.MyObject) %>
<p>
<input type="submit" value="Save" />
</p>
<% } %>
<div>
<%:Html.ActionLink("Back to List", "Index") %>
</div>
Finally, the editor for MyObject:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<TxRP.Models.MyObject>" %>
<%--EditorTemplate--%>
<fieldset>
<div class="editor-label"><%:Html.LabelFor(model => model.MyObjectId)%></div>
<div class="editor-field">
<%:Html.TextBoxFor(model => model.MyObjectId)%>
<%= Html.ValidationMessageFor(model => model.MyObjectId) %>
</div>
<div class="editor-label"><%:Html.LabelFor(model => model.Title)%></div>
<div class="editor-field">
<%:Html.TextAreaFor(model => model.Title, new { cols = "80" })%>
<%= Html.ValidationMessageFor(model => model.Title)%>
</div>
I have Client validation set, and all the scripts are in the master page:
<script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftMvcJQueryValidation.js" type="text/javascript"></script>
<script src="../../scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/ui/minified/jquery.ui.core.min.js" type="text/javascript"></script>
<script src="../../Scripts/ui/minified/jquery.ui.datepicker.min.js" type="text/javascript"></script>
<link href="../../Content/Site.css" type="text/css" rel="Stylesheet" />
<link href="../../Content/jquery-ui/sunny/jquery-ui-1.8.4.custom.css" type="text/css" rel="Stylesheet" />
When I click the Save button, no validation happens. No client validation, no server validation (it doesn't even seem to hit the Post create action at all!); it just bombs on the entity framework model with a ConstraintException, because Title is null. Argh!
I'm sure it's just some silly thing I've overlooked, but I know I had it working at one point, and now it's not, and I've been trying to figure this out all week. Thanks for any help, I'm developing a callous on my forehead from banging it on my desk!
EDIT: Here is the controller:
public ActionResult Create(MyObject myObject)
{
if (!ModelState.IsValid)
{
//ModelState is invalid
return View(new MyObject());
}
try
{
//TODO: Save MyObject
return RedirectToAction("Index");
}
catch
{
//Invalid - redisplay with errors
return View(new MyObject());
}
}
and the exception stack trace:
at System.Data.Objects.DataClasses.StructuralObject.SetValidValue(String value, Boolean isNullable)
at MyProject.Models.MyObject.set_Title(String value) in C:\CodeProjects\MyProject\Models\MyProjectDB.Designer.cs:line 4941