MVC4验证DataAnnotations无效(未验证)

时间:2013-04-01 15:39:15

标签: c# asp.net-mvc validation data-annotations

我有一个相当复杂的模型和一个视图(下图)。我只有一个必填项(Key Active Mg)。当我标记此[Required(ErrorMessage="Key Active Mg is required")]并为该字段设置@Html.ValidationMessageFor时,我的应用将允许我输入任何内容,然后点击保存。当然,Model.IsValid会返回false。它没有返回并以红色标出该字段,表明它是必需的。有谁知道为什么?

我的模特:

    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; }
    }

我的观点:

@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>

我的控制器:

[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");
            }
        }

我的截图:

enter image description here

更新

我已将控制器代码更新为以下内容:

    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();
    }

这解决了我的问题。我需要返回相同的视图以在屏幕上显示错误。使用DataAnnotations Validation,表单确实命中了Create的HttpPost方法,如果有错误(验证错误),ModelState.IsValid将返回false,在这种情况下我需要返回相同的视图。见下面的截图!

enter image description here

4 个答案:

答案 0 :(得分:5)

如果ModelState.IsValidfalse,您似乎正在返回另一个视图( 错误 )。您应该将发布的viewmodel返回到相同的创建视图。

public ActionResult Create(RawValues model)
{
  if(ModelState.IsValid)
  {
     //everything is good. Lets save and redirect
  }
  return View(model);
}

答案 1 :(得分:0)

我的猜测是你没有包括'jquery.unobtrusive-ajax.min.js'和/或'jquery.validate.unobtrusive.min.js'。我相信这些是解释DataAnnotations添加的元数据并提供您要查找的验证方法所必需的。

答案 2 :(得分:0)

当您的模型无效时,您实际上不会返回它的验证错误。然后,你这样做:

@Html.ValidationMessageFor(model => model.KeyActiveMg)

但是没有任何验证消息。您返回了一个包含空白模型的全新视图。相反,您应该将无效模型返回到视图中,如下所示:

return View(rawvalues);

<强>更新

您的控制器应如下所示:

public ActionResult Create()
{
    return View(new RawValues());
}

[HttpPost]
public ActionResult Create(RawValues model)
{
    if (ModelState.IsValid)
    {
        // Do stuff
    }
    else
    {
        return View(model);
    }
}

您的观点似乎很好,所以它应该可以在这里工作。

如果您正在讨论客户端验证,则需要引用必要的JS文件。它们应该已经在Bundle配置中预先配置好了。您只需要添加到您的视图中:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
@Scripts.Render("~/bundles/jqueryval")

为了确保,位于App_Start文件夹中的BundleConfig类应具有以下内容:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
            "~/Scripts/jquery-ui-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
            "~/Scripts/jquery.unobtrusive*",
            "~/Scripts/jquery.validate*"));

答案 3 :(得分:0)

我认为你需要这个

[HttpPost]
public ActionResultCreate(RawValues model)
{
 ....

 if (!ModelState.IsValid)
 {
    ModelState.AddModelError("KeyActiveMg", "KeyActiveMg field is required");
    var model = new GetModel();
    return View("Results", model);
 }  

    rawvaluesRepository.InsertOrUpdate(rawvalues);
    rawvaluesRepository.Save();
    List<Results> results = Helpers.OperationContext.CallCalculate(rawvalues);
    return View("Results", results);
}