I have a pretty complex model and a view (below). I only have ONE of my fields as Required (Key Active Mg). When I mark this [Required(ErrorMessage="Key Active Mg is required")] and set the @Html.ValidationMessageFor for that field, my app will let me enter nothing and click Save. Of course, Model.IsValid will return false. It doesn't come back and outline the field in red indicating it's required. Does anyone know why?
My model:
public class RawValues
{
[Key]
public int Pk { get; set; }
public int? FillerFk { get; set; }
[Display(Name = "Filler")]
[ForeignKey("FillerFk")]
public virtual Filler Filler { get; set; }
public int? CapsuleFk { get; set; }
[Display(Name = "Capsule")]
[ForeignKey("CapsuleFk")]
public virtual Capsule Capsule { get; set; }
public int? KeyActiveFk { get; set; }
[Display(Name = "Key Active")]
[ForeignKey("KeyActiveFk")]
public virtual KeyActive KeyActive { get; set; }
[Display(Name="API #1")]
public int? Active1 { get; set; }
[Display(Name = "API #2")]
public int? Active2 { get; set; }
[Display(Name = "API #3")]
public int? Active3 { get; set; }
[Display(Name = "API #4")]
public int? Active4 { get; set; }
[Display(Name = "API #5")]
public int? Active5 { get; set; }
[Display(Name = "Key Active Mg")]
[Required(ErrorMessage="Key Active Mg is required.")]
public int KeyActiveMg { get; set; }
[Display(Name = "E4M")]
public bool E4M { get; set; }
[Display(Name = "K100M")]
public bool K100M { get; set; }
public int TimeReleaseFillerFk { get; set; }
public int NumberCapsules { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
}
My View:
@model CapWorx.QuikCap.Models.RawValues
@* This partial view defines form fields that will appear when creating and editing entities *@
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Capsule, new { @class = "ui-input-text" })
@Html.DropDownListFor(m => m.Capsule.Pk, new SelectList(ViewBag.Capsules, "Pk", "Name", "Pk"))
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Active1)
@Html.EditorFor(model => model.Active1)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Active2)
@Html.EditorFor(model => model.Active2)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Active3)
@Html.EditorFor(model => model.Active3)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Active4)
@Html.EditorFor(model => model.Active4)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Active5)
@Html.EditorFor(model => model.Active5)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.KeyActive, new { @class = "ui-input-text" })
@Html.DropDownListFor(m => m.KeyActive.Pk, new SelectList(ViewBag.KeyActives, "Pk", "Name", "Pk"))
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.KeyActiveMg)
@Html.EditorFor(model => model.KeyActiveMg)
@Html.ValidationMessageFor(model => model.KeyActiveMg)
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.E4M)
@Html.DropDownListFor(x => x.E4M,
new[] {
new SelectListItem() { Text = "Off", Value = "False", Selected = true },
new SelectListItem() { Text = "On", Value = "True" } },
new { data_role = "slider" })
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.K100M)
@Html.DropDownListFor(x => x.K100M,
new[] {
new SelectListItem() { Text = "Off", Value = "False", Selected = true },
new SelectListItem() { Text = "On", Value = "True" } },
new { data_role = "slider" })
</div>
<div data-role="fieldcontain">
@Html.LabelFor(model => model.Filler, new { @class = "ui-input-text" })
@Html.DropDownListFor(m => m.Filler.Pk, new SelectList(ViewBag.Fillers, "Pk", "Name", "Pk"))
@Html.ValidationMessage("FillerName", "Filler is required")
</div>
My Controller:
[HttpPost]
public ActionResult Create(RawValues rawvalues)
{
rawvalues.CreatedBy = User.Identity.Name;
rawvalues.CreatedDate = DateTime.Now;
rawvalues.TimeReleaseFillerFk = Helpers.OperationContext.GetTimeReleaseFillerFk(rawvalues.E4M, rawvalues.K100M);
rawvalues.CapsuleFk = rawvalues.Capsule.Pk;
rawvalues.FillerFk = rawvalues.Filler.Pk;
rawvalues.KeyActiveFk = rawvalues.KeyActive.Pk;
rawvalues.Filler = Helpers.OperationContext.GetFiller(rawvalues.Filler.Pk);
rawvalues.Capsule = Helpers.OperationContext.GetCapsule(rawvalues.Capsule.Pk);
rawvalues.KeyActive = Helpers.OperationContext.GetKeyActive(rawvalues.KeyActive.Pk);
rawvalues.NumberCapsules = 100;
var errors = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid) {
rawvaluesRepository.InsertOrUpdate(rawvalues);
rawvaluesRepository.Save();
List<Results> results = Helpers.OperationContext.CallCalculate(rawvalues);
return View("Results", results);
} else {
ViewBag.Error = "Model State was not valid.";
return View("Error");
}
}
My screenshot:

UPDATE
I've updated my controller code to be the following:
if (ModelState.IsValid) {
rawvaluesRepository.InsertOrUpdate(rawvalues);
rawvaluesRepository.Save();
List<Results> results = Helpers.OperationContext.CallCalculate(rawvalues);
return View("Results", results);
} else {
ViewBag.Capsules = Helpers.OperationContext.GetCapsules();
ViewBag.Fillers = Helpers.OperationContext.GetFillers();
ViewBag.KeyActives = Helpers.OperationContext.GetKeyActives();
return View();
}
This resolves my issue. I needed to return the same View to display the errors on the screen. With DataAnnotations Validation, the form does in fact hit the HttpPost method of Create, and if there are errors (validation errors) the ModelState.IsValid will return false, in which case I need to return the same view. See screenshot below!
