代码之家  ›  专栏  ›  技术社区  ›  Alex P

强类型视图的MVC验证错误

  •  0
  • Alex P  · 技术社区  · 16 年前

    我有一个简单的表单,我想在表单提交时验证它。注意:为了便于查看,我去掉了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>
       <% } %>  
    

    在提交这份表格时,我想核对一下 FirstName 和 LastName 填充(即非零长度)。

    在我的控制器中,我有:

    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
    }
    

    不幸的是,此代码逻辑产生一个错误,该错误指出找不到 JobRole 和 Courses .

    如果我删除DropDownlist和复选框,那么一切都可以正常工作。

    问题似乎是当我返回 View 视图需要DropDownList和复选框的对象(这是合理的,因为这就是我的视图代码中的对象)。

    我怎样才能克服这个问题?

    我考虑过的事情:

    1. 在我的控制器中,我可以创建一个 JobRoleList 对象和 Course 对象以传递到视图,使其具有要渲染的对象。与此相关的问题是,它将覆盖用户已经做出的任何DropDownList/CheckBox选择。
    2. 在我的控制器方法的参数中 Submit 我也能抓住 求职者 对象和 课程 要返回到视图的对象。同样,不确定这是否会捕获用户已选择的任何项目。

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

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

    谢谢

    2 回复  |  直到 16 年前
        1
  •  1
  •   tvanfosson    16 年前

    最佳实践是接受特定于视图的模型。您可以拥有一个共享模型,该模型既具有呈现页面所需的属性,也具有发布时所需的属性,或者具有单独模型用于呈现和接受发布参数的属性。我通常使用共享模型,因为这意味着我可以简单地返回我收到的模型,适当地重新填充生成菜单所需的任何数据(如工作列表和课程)。通常我会有一个方法,它采用这种类型的模型并返回一个填充了菜单属性的视图。

       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>
       <% } %>  
    
        2
  •  0
  •   Michael D. Irizarry    16 年前

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

    例子:

    public ActionResult Update(Employees employee)
    {
    
    if (employee.Name.Trim().Length == 0)
            ModelState.AddModelError("Name", "Name is required.");
    
    // ETC....
    
    }