MVC 验证基础(使用实体框架)
设想:
我有一个模型类如下(通过实体框架 EF.x DbContext 生成器自动生成)。
(目前没有视图模型)。
public partial class Activity
{
public int Id { get; set; }
public byte Progress { get; set; }
public decimal ValueInContractCurrency { get; set; }
public System.DateTime ForecastStart { get; set; }
public System.DateTime ForecastEnd { get; set; }
public int DepartmentId { get; set; }
public int OwnerId { get; set; }
public int StageId { get; set; }
public int StatusId { get; set; }
public virtual Department Department { get; set; }
public virtual Owner Owner { get; set; }
public virtual Stage Stage { get; set; }
public virtual Status Status { get; set; }
}
当我在强类型视图上提交空白表单时,我会收到以下验证消息:
进度字段是必需的。
ValueInContractCurrency 字段是必需的。
ForecastStart 字段是必需的。
ForecastEnd 字段是必需的。
即 db 表中的所有字段。
如果我填写这些并再次提交,那么控制器就会被调用。由于 IsValid 为假,控制器然后返回到视图页面。
然后屏幕会重新显示这些验证消息:
StageId 字段是必需的。
DepartmentId 字段是必需的。
StatusId 字段是必需的。
OwnerId 字段是必需的。
即 db 表中的所有外键字段(这些也是所有选择框)。
如果我填写这些,表单就会成功提交并保存到数据库中。
问题:
鉴于我没有使用任何 [Required] 属性,验证从何而来?这与实体框架有关吗?
为什么表单没有立即在客户端验证所有内容,外键(或选择框)有什么不同,它们仅由 IsValid() 检查,即使它们是空的,因此显然无效?
您如何使所有内容都在一个步骤中得到验证(对于空字段),因此用户不必提交两次表单并且所有验证消息都会立即显示?您是否必须关闭客户端验证?
(我尝试将 [Required] 属性添加到外键字段,但这似乎没有任何区别(可能它们只影响 IsValid)。我也尝试调用 Html.EnableClientValidation() 但这也没有任何区别)。
4..最后,我看到有人使用 [MetadataType[MetadataType(typeof(...)]] 进行验证。如果您有视图模型,为什么要这样做,或者只有在没有视图模型时才这样做?
显然我在这里遗漏了一些基础知识,因此,如果有人知道有关 MVC 验证过程如何逐步工作的详细教程,包括 javascript/controller 调用,而不仅仅是关于属性的另一篇文章,那么我可以做也有一个链接:c)
更多关于神秘人的信息:
解决方案设置如下:
.NET4
MVC3
EF5
EF5.x Db 上下文生成器
在 edmx 设计表面上使用“添加代码生成项”来关联 EF.x Db 上下文生成器文件(.tt 文件)
控制器如下所示:
// GET: /Activities/Create
public ActionResult Create()
{
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name");
ViewBag.OwnerId = new SelectList(db.Owners, "Id", "ShortName");
ViewBag.ContractId = new SelectList(db.Contracts, "Id", "Number");
ViewBag.StageId = new SelectList(new List<string>());
ViewBag.StatusId = new SelectList(db.Status.Where(s => s.IsDefaultForNewActivity == true), "Id", "Name");
return View();
}
// POST: /Activities/Create
[HttpPost]
public ActionResult Create(Activity activity)
{
if (ModelState.IsValid)
{
db.Activities.Add(activity);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name");
ViewBag.OwnerId = new SelectList(db.Owners, "Id", "ShortName");
ViewBag.ContractId = new SelectList(db.Contracts, "Id", "Number");
ViewBag.StageId = new SelectList(db.Stages, "Id", "Number");
ViewBag.StatusId = new SelectList(db.Status, "Id", "Name");
return View(activity);
}
视图是这样的:
<!-- this refers to the EF.x DB Context class shown at the top of this post -->
@model RDMS.Activity
<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>Activity</legend>
<div class="editor-label">
@Html.LabelFor(model => model.StageId, "Stage")
</div>
<div class="editor-field">
@Html.DropDownList("StageId", String.Empty)
@Html.ValidationMessageFor(model => model.StageId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Progress)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Progress)
@Html.ValidationMessageFor(model => model.Progress)
</div>
<!-- ETC...-->
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}