2010-06-03 66 views
0

我有一个简单的表单,我想验证表单提交。请注意我已经剥离出来的HTML,以便于查看MVC验证错误与强类型视图

<%=Html.TextBox("LastName", "")%> //Lastname entry 
<%=Html.ValidationMessage("LastName")%> 

<%=Html.TextBox("FirstName", "")%>//Firstname entry 
<%=Html.ValidationMessage("FirstName")%> 

<%=Html.DropDownList("JobRole", Model.JobRoleList)%> //Dropdownlist of job roles 

<% foreach (var record in Model.Courses) // Checkboxes of different courses for user to select 
    { %> 
     <li><label><input type="checkbox" name="Courses" value="<%=record.CourseName%>" /><%= record.CourseName%></label></li> 
    <% } %> 

在提交此申请表的,我想检查两个FirstNameLastName被填充(即非0的长度)。

在我的控制,我有:

public ActionResult Submit(string FirstName, string LastName) 
{ 
    if (FirstName.Trim().Length == 0) 
    ModelState.AddModelError("FirstName", "You must enter a first name"); 

    if (LastName.Trim().Length == 0) 
    ModelState.AddModelError("LastName", "You must enter a first name"); 

    if (ModelState.IsValid) 
    { 
     //Update database + redirect to action 
    } 

    return View(); //If ModelState not valid, return to View and show error messages 
} 

不幸的是,这种代码逻辑产生,说明没有对象被发现JobRoleCourses错误。

如果我删除下拉列表和复选框,那么一切正常。

的问题似乎是,当我返回View视图期待的对象为dropwdownlist和复选框(这是明智的,因为这是什么,在我看来代码)

我怎样才能解决这个问题?

事情我已经考虑:

  1. 在我的控制,我可以创造一个JobRoleList对象和Course对象传递给视图,以便它有渲染的对象。与此相关的问题是它将覆盖用户已经做出的任何下拉列表/复选框选择。
  2. 在我的控制器方法Submit的参数中,我可以同时捕获JobRoleList对象和Course对象以传递回视图。再次,不确定这将捕获用户已经选择的任何项目。

我已经做了很多谷歌搜索和阅读,但我找不到一个好的答案。当我在书籍或在线(例如Nerddinner)中查看示例时,所有验证示例都涉及带有TextBox输入的简单表单,并且似乎并未显示具有多个复选框和下拉列表的实例。

我在这里遗漏了一些明显的东西吗?在这种情况下最好的做法是什么?

感谢

回答

1

最好的做法将是接受视图特定的模型。您可以拥有一个共享模型,该模型既具有呈现页面所需的属性,也具有用于呈现和接受发布参数的发布或独立模型所需的属性。我通常使用共享模式,因为这意味着我可以简单地返回我收到的模型,适当地重新填充生成菜单所需的任何数据(例如JobList和Courses)。通常我会有一个采用这种类型模型的方法,并返回一个视图,其中填充了菜单属性。

public ActionResult JobsView(JobsViewModel model) 
    { 
     model.JobList = db.Jobs.Select(j => new SelectListItem 
              { 
                Text = j.Name, 
                Value = j.ID.ToString() 
              }); 
     ... 
     return View(model); 
    } 

然后从任何我的行动需要这种类型的模型的视图,这种方法以保证模型具有适当的菜单数据。

// on error, return the view 
    return JobsView(model); 

当使用一个模型,您还可以使用DataAnnotations来装饰你的模特属性,让模型绑定基于该模型为你做验证,以及启用客户端验证。现有属性不支持的任何验证都可以通过创建自己的属性或在控制器操作中完成。

public class JobsViewModel 
    { 
     [Required] 
     public string FirstName { get; set; } 

     [Required] 
     public string LastName { get; set; } 

     public int JobRole { get; set; } 

     [ScaffoldColumn(false)] 
     public IEnumerable<SelectListItem> JobRoleList { get; set; } 

     ... 
    } 

    public ActionResult Submit(JobsViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      ... convert model to entity and save to DB... 
     } 

     return JobsView(model); 
    } 

然后在你的HTML

... 
<script type="text/javascript" src="<%= Url.Content("~/scripts/MicrosoftMvcValidation.js") %>"></script> 

<% Html.EnableClientValidation(); %> 

... begin form... 

<%=Html.TextBoxFor(m=> m.LastName)%> 
<%=Html.ValidationMessageFor(m => m.LastName)%> 

<%=Html.TextBoxFor(m=> m.FirstName)%> 
<%=Html.ValidationMessageFor(m => m.FirstName)%> 

<%=Html.DropDownListFor(m=> m.JobRole, Model.JobRoleList)%> 

<% foreach (var record in Model.Courses) // Checkboxes of different courses for user to select 
    { %> 
     <li><label><input type="checkbox" name="Courses" value="<%=record.CourseName%>" /><%= record.CourseName%></label></li> 
    <% } %> 
+0

感谢启用验证。我已经采用了你的方法,现在事情都很好。它确实觉得我的ViewModel有点臃肿,我可能会或可能不会使用数据,但对于我所做的事情,我不认为它会给我带来任何问题。感谢您花时间为我提供建议。 – 2010-06-03 20:20:58

+0

@ Remnant-正如我所说的,你可以有独立的模型(在适当的情况下使用子类化)来显示/发布,但是当你发生错误时,你需要一种方法在它们之间进行转换,而不是仅填充缺失的位。 – tvanfosson 2010-06-03 21:05:40

0

在简单的MVC确认您应该通过换句话说,你的意见模型中的强类型的对象。

实施例:

public ActionResult Update(Employees employee) 
{ 

if (employee.Name.Trim().Length == 0) 
     ModelState.AddModelError("Name", "Name is required."); 

// ETC.... 

}