具有强类型视图的MVC验证错误

时间:2010-06-03 11:21:47

标签: c# asp.net-mvc validation

我有一个简单的表单,我想在表单提交上验证。注意我已经删除了html以便于查看

<%=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是否已填充(即非零长度)。

在我的控制器中我有:

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时,视图期望下拉列表和复选框的对象(这是明智的,因为这是我的View代码中的内容)

我该如何克服这个问题?

我考虑过的事情:

  1. 在我的控制器中,我可以创建一个JobRoleList对象和Course对象以传递给View,以便它具有要渲染的对象。这个问题是它将覆盖用户已经做过的任何下拉列表/复选框选择。
  2. 在我的控制器方法Submit的参数中,我可以捕获JobRoleList对象和Course对象以传回View。同样,不确定这会捕获用户已选择的任何项目。
  3. 我做了很多谷歌搜索和阅读,但我找不到一个好的答案。当我查看书籍或在线(例如Nerddinner)中的示例时,所有验证示例都涉及使用TextBox输入的简单表单,并且似乎不显示具有多个复选框和下拉列表的实例。

    我错过了一些明显的东西吗?在这种情况下最佳做法是什么?

    由于

2 个答案:

答案 0 :(得分: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>
   <% } %>  

答案 1 :(得分:0)

在简单的MVC验证中,您应该传递强类型对象,换句话说,您的视图模型。

示例:

public ActionResult Update(Employees employee)
{

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

// ETC....

}