【问题标题】:Validation for DropDownLists Broken验证 DropDownLists Broken
【发布时间】:2021-03-19 07:36:40
【问题描述】:

这与previous question 相关,该previous question 将模型数据从两个 DropDownLists 传递到部分视图,其中用户必须在视图中选择部门和年份。然后数值数据显示在局部视图的表格中。该视图包含下拉列表和表格标题。局部视图包含带有数字数据的行。现在,验证被破坏了。这两个下拉菜单都是必需的。如果我提交表单时未选择任一下拉菜单,则会收到此错误:

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has
the key 'SelectedDepartment'

此行出现错误:

@Html.DropDownListFor(m => m.SelectedDepartment, Model.Departments,
    "Select Department", new { @class = "form-control" })

当它碰到控制器时,模型状态无效。

查看:

@model BudgetDemo.Models.BudgetsActualsViewModel

@using (Html.BeginForm("GetBudgetsActuals", "BudgetsActuals", FormMethod.Post))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="col-md-6">
        <div class="form-group">
            @Html.DropDownListFor(m => m.SelectedDepartment, Model.Departments, 
                "Select Department", new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.SelectedDepartment, "", 
                new { @class = "text-danger" })
        </div>
    </div>
    <div class="col-md-6">
        <div class="form-group">
            @Html.DropDownListFor(m => m.SelectedYear, Model.Years, "Select Year", 
                new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.SelectedYear, "", 
                new { @class = "text-danger" })
        </div>
   </div>

   <div class="form-group">
       <div class="col-lg-7">
           <input type="submit" value="Submit" class="btn btn-info" />
       </div>
   </div>

    @if (Model.SelectedDepartment != null && Model.SelectedYear != null)
    {
        // table headers, etc
        @if (Model != null)
        {
            Html.RenderPartial("_BudgetsActuals", Model.BudgetActualCollection);
        }
    } 
}

型号:

    public class BudgetsActualsViewModel
    {
        // Cost Center / Department Drop Down
        [Display(Name = "Cost Center/Department")]
        [Required(ErrorMessage = "Cost Center/Department is required.")]
        [StringLength(62)]
        public string SelectedDepartment { get; set; }
        public List<SelectListItem> Departments { get; set; }
    
        // Year Drop Down
        [Display(Name = "Year")]
        [Required(ErrorMessage = "Year is required.")]
        public string SelectedYear { get; set; }
        public List<SelectListItem> Years { get; set; }
    
        // Account and Name fields
        [Display(Name = "Account")]
        [StringLength(9)]
        public string Account { get; set; }
    
        [Display(Name = "Name")]
        [StringLength(12)]
        public string CostCenter { get; set; }
    
        // Seven calculated fields: Oct Actual, Oct Budget, YTD Actual, YTD 
        // Budget, YTD Variance, Est To Complete, Est at Complete
        [Display(Name = "TotalCurrentMonthActualConversion", 
        ResourceType = typeof(DynamicDisplayAttributeNames))]
        public int TotalCurrentMonthActual { get; set;  }
    
        [Display(Name = "TotalCurrentMonthBudgetConversion", 
            ResourceType = typeof(DynamicDisplayAttributeNames))]
        public int TotalCurrentMonthBudget { get; set; }
    
        [Display(Name = "YTD Actual", AutoGenerateFilter = false)]
        public int TotalYTDActual { get; set; }
    
        [Display(Name = "YTD Budget", AutoGenerateFilter = false)]
        public int TotalYTDBudget { get; set; }
    
        [Display(Name = "YTD Variance", AutoGenerateFilter = false)]
        public int TotalVariance { get; set; }
    
        [Display(Name = "Est to Complete", AutoGenerateFilter = false)]
        public int TotalETCBudget { get; set; }
    
        [Display(Name = "Est at Complete", AutoGenerateFilter = false)]
        public int TotalEAC { get; set; }
    }
    
    public class DynamicDisplayAttributeNames
    {
        public static string TotalCurrentMonthActualConversion { get; set; } 
            = DateTime.Now.AddMonths(-1).ToString("MMM") + " Actual";
        public static string TotalCurrentMonthBudgetConversion { get; set; } 
            = DateTime.Now.AddMonths(-1).ToString("MMM") + " Budget";
    }

控制器:

// POST: Grab data for department and year
[HttpPost]
public ActionResult GetBudgetsActuals(BudgetsActualsViewModel model)
{
    try
    { 
        if (ModelState.IsValid)
        {
            var repo = new BudgetDemoRepository();
            ModelState.Clear();

            model.Departments = repo.GetBudgetsActuals().Departments;
            model.Years = repo.GetBudgetsActuals().Years;
            model.BudgetActualCollection = repo.GetBudgetsActualsData(model);
         }
         else
         {
             // Execution gets to here before returning to view
             model.BudgetActualCollection = new 
                 List<BudgetDemo.Models.BudgetsActualsViewModel>();
         }
         return View(model);
    }
    catch
    {
         return View("Error");
    }
}

【问题讨论】:

  • 您有客户端验证吗?那么当用户点击提交按钮时,它会在提交之前显示错误?如果不是,它会提交表单,并且在控制器中ModelState.IsValid 始终为 false,因此下拉集合中没有数据。尝试在Try-Catch 之外分配model.Departments = repo.GetBudgetsActuals().Departments; model.Years = repo.GetBudgetsActuals().Years;,以便在将视图返回为done here 之前始终具有值。您的收藏将在回发时丢失数据。
  • 现在客户端验证工作正常,我缺少“jquery.validate.unobtrusive.min.js”。现在,当我在下拉列表中进行选择时,不会显示任何数据 - 只是一个模式弹出窗口说“已提交!”
  • “现在,当我在下拉列表中进行选择时,不会显示任何数据 - 只是一个模式弹出窗口说“已提交!” - 这是什么意思?您不必提交表单以在部分视图中填充数据吗?您现在看到客户端验证了吗?当您同时选择两个下拉菜单并提交表单时会发生什么?
  • @Pirate,当我在两个下拉菜单中进行选择并单击“提交”时,会出现一个模式,显示“已提交!”。当我在模式上单击“确定”时,没有其他任何反应。想知道这是否与 Bootstrap 有关?
  • 但为什么会打开模态?这是您在提交之前已经准备好的东西吗?如果是这样,您需要在模式上绑定 OK 事件以使用 javascript 提交表单。类似$('#formId').submit();

标签: c# asp.net asp.net-mvc asp.net-mvc-5


【解决方案1】:

这似乎是HttpPost 方法的问题。提交表单时,集合没有通过,因此我们丢失了其中的数据。现在,HttpPost 方法返回相同的视图,但它只分配 if 块中的集合,因此当缺少任何一个下拉列表时,if 状态将为 false 并且执行将进入 else 块和将返回带有模型的视图。在这种情况下,集合从未分配过数据。将HttpPost 更新到下面,这样无论其他条件如何都会填充集合。

// POST: Grab data for department and year
[HttpPost]
public ActionResult GetBudgetsActuals(BudgetsActualsViewModel model)
{
    try
    { 
         // assign collections before returning view
         var repo = new BudgetDemoRepository();
         model.Departments = repo.GetBudgetsActuals().Departments;
         model.Years = repo.GetBudgetsActuals().Years;

         if (ModelState.IsValid)
         {            
            ModelState.Clear();            
            model.BudgetActualCollection = repo.GetBudgetsActualsData(model);
         }
         else
         {
             model.BudgetActualCollection = new 
                 List<BudgetDemo.Models.BudgetsActualsViewModel>();
         }
         return View(model);
    }
    catch
    {
         return View("Error");
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 2014-05-30
    • 2011-03-25
    • 2014-01-15
    相关资源
    最近更新 更多