C# 强类型视图的MVC验证错误

C# 强类型视图的MVC验证错误,c#,asp.net-mvc,validation,C#,Asp.net Mvc,Validation,我有一个简单的表单,我想在提交表单时验证它。注意:为了便于查看,我去掉了html <%=Html.TextBox("LastName", "")%> //Lastname entry <%=Html.ValidationMessage("LastName")%> <%=Html.TextBox("FirstName", "")%>//Firstname entry <%=Html.ValidationMessage("FirstName")%>

我有一个简单的表单,我想在提交表单时验证它。注意:为了便于查看,我去掉了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>
   <% } %>  
不幸的是,此代码逻辑产生一个错误,表明未找到
JobRole
课程的对象

如果我删除了dropdownlist和复选框,那么一切正常

问题似乎是当我返回
视图时
视图需要dropwdownlist和复选框中的对象(这是合理的,因为这是我的视图代码中的内容)

我怎样才能克服这个问题

我考虑过的事情:

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

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


    感谢

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

    例如:

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

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

       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 );
      }
    
    公共类JobsViewModel
    {
    [必需]
    公共字符串名{get;set;}
    [必需]
    公共字符串LastName{get;set;}
    公共int作业角色{get;set;}
    [脚手架立柱(假)]
    公共IEnumerable作业列表{get;set;}
    ...
    }
    公共行动结果提交(JobsViewModel模型)
    {
    if(ModelState.IsValid)
    {
    …将模型转换为实体并保存到数据库。。。
    }
    返回作业视图(模型);
    }
    
    然后在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>
       <% } %>  
    
    。。。
    ... 开始形式。。。
    m、 姓氏)%%>
    m、 姓氏)%%>
    m、 名字)%%>
    m、 名字)%%>
    m、 JobRole,Model.JobRoleList)%%>
    

  • 谢谢。我采用了你的方法,现在一切都很顺利。我确实觉得我的ViewModel中的数据有点臃肿,我可能会使用,也可能不会使用,但对于我正在做的事情,我并不认为它会给我带来任何问题。谢谢你花时间给我提建议。@rement-正如我所说的,你可以为display/post使用单独的模型(如果合适的话使用子类化),但是当你有错误时,你需要一种在它们之间转换的方法,而不仅仅是填充缺失的位。
    ...
    <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>
       <% } %>