DropDownLists 的验证已损坏
Validation for DropDownLists Broken
这与 将模型数据从两个 DropDownList 传递到部分视图有关,其中用户必须 select 视图中的部门和年份。然后数值数据显示在局部视图的 table 中。该视图包含下拉菜单和 table headers。分部视图包含带有数值数据的行。现在,验证被打破了。两个下拉菜单都是必需的。如果我提交的表单没有 selected,我会得到这个错误:
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");
}
}
这似乎是 HttpPost
方法的问题。提交表单时,集合未通过,因此我们丢失了其中的数据。现在,HttpPost
方法 return 相同的视图,但它只分配 if
块中的集合,因此当缺少任何一个下拉列表时, if
状态将为 false执行将进入 else
块,并将 return 与模型一起查看。在这种情况下,集合从未分配数据。将 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");
}
}
这与
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");
}
}
这似乎是 HttpPost
方法的问题。提交表单时,集合未通过,因此我们丢失了其中的数据。现在,HttpPost
方法 return 相同的视图,但它只分配 if
块中的集合,因此当缺少任何一个下拉列表时, if
状态将为 false执行将进入 else
块,并将 return 与模型一起查看。在这种情况下,集合从未分配数据。将 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");
}
}