如何将项目列表从视图传递到控制器(ASP.NET MVC 4)

我正在尝试将List 类型的多个项目传递给我的控制器,但是,当我提交数据时,它在我的控制器中显示为null。

我想要发生的是,我在视图中有一个“费用”列表,并且每个“费用”或项目旁边都是我的模型中的“已提交的布尔”属性的复选框。 当我检查项目时,我希望在数据库中更新已检查项目的属性列表SubmittedDateSubmitted

View中的@ Html.DisplayFor(modelItem => item.Submitted)生成复选框。

我究竟做错了什么?

这是我的观点:

@model IEnumerable @{ ViewBag.Title = "Submit Expenses"; Layout = "~/Views/Shared/_Layout.cshtml"; DateTime today = DateTime.Today; string formattedDate = today.ToString("MM/dd/yyyy"); }    

Submit Expenses

@using (Html.BeginForm()) { @Html.AntiForgeryToken()

Start Date:

@Html.TextBox("expenseDate", formattedDate, htmlAttributes: new { @class = "form-control" })

End Date:

@Html.TextBox("expenseDate2", formattedDate, htmlAttributes: new { @class = "form-control" })
@if (User.IsInRole("admin")) {

Username:

@Html.DropDownList("UserId", String.Empty)
}




@Html.ActionLink("Create New", "Create")

@if (User.IsInRole("admin")) { } @foreach (var item in Model) { @if (User.IsInRole("admin")) { } }
@Html.DisplayNameFor(model => model.Company) @Html.DisplayNameFor(model => model.Category) @Html.DisplayNameFor(model => model.Province) @Html.DisplayNameFor(model => model.ReceiptName) @Html.DisplayNameFor(model => model.Comment) @Html.DisplayNameFor(model => model.GrossAmount) @Html.DisplayNameFor(model => model.TaxAmount) @Html.DisplayNameFor(model => model.NetAmount) @Html.DisplayNameFor(model => model.Mileage) @Html.DisplayNameFor(model => model.TravelStatus) @Html.DisplayNameFor(model => model.LunchLearnStatus) @Html.DisplayNameFor(model => model.WithClientStatus) @Html.DisplayNameFor(model => model.DateEntered) @Html.DisplayNameFor(model => model.DateSubmitted) @Html.DisplayNameFor(model => model.ExpenseDate) @Html.DisplayNameFor(model => model.ImageName) @Html.DisplayNameFor(model => model.UserProfile.UserName)
Select All:
@Html.EditorFor(modelItem => item.Submitted) @Html.DisplayFor(modelItem => item.Company) @Html.DisplayFor(modelItem => item.Category) @Html.DisplayFor(modelItem => item.Province) @Html.DisplayFor(modelItem => item.ReceiptName) @Html.DisplayFor(modelItem => item.Comment) @Html.DisplayFor(modelItem => item.GrossAmount) @Html.DisplayFor(modelItem => item.TaxAmount) @Html.DisplayFor(modelItem => item.NetAmount) @Html.DisplayFor(modelItem => item.Mileage) @Html.DisplayFor(modelItem => item.TravelStatus) @Html.DisplayFor(modelItem => item.LunchLearnStatus) @Html.DisplayFor(modelItem => item.WithClientStatus) @Html.DisplayFor(modelItem => item.DateEntered) @Html.DisplayFor(modelItem => item.DateSubmitted) @Html.DisplayFor(modelItem => item.ExpenseDate) @if (item.ImageName != null) { item.UserProfile.FullName)/@Html.DisplayFor(modelItem => item.ImageName)" class="imageClick" target="_blank"> item.UserProfile.FullName)/@Html.DisplayFor(modelItem => item.ImageName)" alt="Image" style="width:80%" /> } @Html.DisplayFor(modelItem => item.UserProfile.UserName) @Html.ActionLink("Edit", "Edit", new { id = item.ExpenseId }) | @Html.ActionLink("Details", "Details", new { id = item.ExpenseId }) | @if (User.IsInRole("admin")) { @Html.ActionLink("Delete", "Delete", new { id = item.ExpenseId }) }
@Html.ActionLink("Submit Expenses", "SubmitExpenses", "Expenses", null, new { @class = "submitLink", @style = "background-color: #d3dce0; border: 1px solid #787878; cursor: pointer; font-size: 1.5em; font-weight: 600; margin-right: 8px; padding: 7px; width: auto; text-decoration: none; font-weight:bold;"})
@*Export To CSV*@ @Html.ActionLink("Export To CSV", "ExportExpensesListToCSV")
} @section scripts { $("#selectAllCheckboxes").click(function () { $('.submitCheck input:checkbox').not(this).prop('checked', this.checked); }); $(function () { $("#expenseDate").datepicker(); }); $(function () { $("#expenseDate2").datepicker(); }); }

这是我的Controller方法:

 public ActionResult SubmitExpenses(List expenses, DateTime? expenseDate = null, DateTime? expenseDate2 = null, int? userId = 0) { expenseDate = (DateTime)Session["FirstDate"]; expenseDate2 = (DateTime)Session["SecondDate"]; if (expenseDate == null || expenseDate2 == null) { expenseDate = DateTime.Now.AddMonths(-1); expenseDate2 = DateTime.Today; } string currentUserId = User.Identity.Name; var query = from e in db.Expenses join user in db.UserProfiles on e.UserId equals user.UserId where e.ExpenseDate >= expenseDate && e.ExpenseDate  x.user.UserId == userId); } else if (!User.IsInRole("admin")) { query = query.Where(x => x.user.UserName == currentUserId); } var expensesFromView = expenses; var joined = from dbExpense in query.Select(x => xe).AsEnumerable() join localExpense in expenses on dbExpense.ExpenseId equals localExpense.ExpenseId where localExpense.Submitted select dbExpense; foreach (Expense exp in joined) { exp.DateSubmitted = DateTime.Today; } try { db.SaveChanges(); return RedirectToAction("Index"); } catch (Exception e) { Console.WriteLine(e); return RedirectToAction("Submit"); } } 

这是我的模型:

 [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int ExpenseId { get; set; } [Required] public string Company { get; set; } [Required] public string Category { get; set; } [Required] [Display(Name = "Receipt Name")] public string ReceiptName { get; set; } public string Comment { get; set; } [Required] public string Province { get; set; } [Required] [Display(Name = "Gross Amount")] public decimal GrossAmount { get; set; } [Required] [Display(Name = "GST/HST Amount")] public decimal TaxAmount { get; set; } [Required] [Display(Name = "Net Amount")] public decimal NetAmount { get; set; } [Display(Name = "Mileage (in Kilometers)")] public int Mileage { get; set; } [Display(Name = "Travelling?")] public bool TravelStatus { get; set; } [Display(Name = "Lunch & Learn?")] public bool LunchLearnStatus { get; set; } [Display(Name = "With Clients?")] public bool WithClientStatus { get; set; } [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] [Required] [Display(Name = "Date Entered")] public DateTime? DateEntered{ get; set; } [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] [Display(Name = "Date Submitted")] public DateTime? DateSubmitted { get; set; } [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] [Required] [Display(Name = "Expense Date")] public DateTime? ExpenseDate { get; set; } [Display(Name = "Image")] public string ImageName { get; set; } [Display(Name = "Submitted?")] public bool Submitted { get; set; } [Required] [Display(Name = "Name")] public int UserId { get; set; } [ForeignKey("UserId")] public virtual UserProfile UserProfile { get; set; } 

我的变量expensesFromView显示为null,因此,我在joined查询中收到错误消息:

值不能为空。 参数名称:inner

有两种方法可以做到这一点 –

1。

您可能需要这个非常好且可扩展的扩展 – MvcCheckBoxList – SEEMS此站点已关闭:)请参阅选项2

2。

 @for (int i = 0; i < Model.Count; i++) {       @Html.DisplayFor(modelItem => item.Company)   } 

顺便说一句:如果你使用第二种方式:在你的控制器中,过滤费用对象的Id的零值; 如果没有被选中,则将零发送到控制器(作为元素的ID),以便在上面的代码中看到“隐藏”字段。

我真的找不到直接从View传递项目列表的方法,所以我决定使用AJAX。

我将Controller的参数从List <>更改为int []以获取项ID的数组:

 public ActionResult SubmitExpenses(int[] expenseIDs, DateTime? expenseDate = null, DateTime? expenseDate2 = null, int? userId = 0) { expenseDate = (DateTime)Session["FirstDate"]; expenseDate2 = (DateTime)Session["SecondDate"]; if (expenseDate == null || expenseDate2 == null) { expenseDate = DateTime.Now.AddMonths(-1); expenseDate2 = DateTime.Today; } string currentUserId = User.Identity.Name; var query = from e in db.Expenses join user in db.UserProfiles on e.UserId equals user.UserId where e.ExpenseDate >= expenseDate && e.ExpenseDate <= expenseDate2 && e.DateSubmitted == null orderby e.ExpenseDate descending select new { e, user }; if (User.IsInRole("admin") && userId != 0) { query = query.Where(x => x.user.UserId == userId); } else if (!User.IsInRole("admin")) { query = query.Where(x => x.user.UserName == currentUserId); } //var localExpenseIDs = expenseIDs; var joined = from dbExpense in query.Select(x => xe).AsEnumerable() join localExpense in expenseIDs on dbExpense.ExpenseId equals localExpense where localExpense == dbExpense.ExpenseId select dbExpense; foreach (Expense exp in joined) { exp.DateSubmitted = DateTime.Today; exp.IsSubmitted = true; } try { db.SaveChanges(); return RedirectToAction("Index"); } catch (Exception e) { Console.WriteLine(e); return RedirectToAction("Submit"); } } 

在我看来,我将每个项目的ID分配给它自己的HTML复选框的id:

 @foreach (var item in Model) {   @Html.CheckBox("isSubmitted", new { @id = @Html.DisplayFor(modelItem => item.ExpenseId), @class = "submitBox" })   } 
@Html.ActionLink("Submit Expenses", "", "", null, new { @id = "submitExpensesLink" })

我写了一些jQuery,以便检查每个复选框,将输入元素的id添加到数组中,整数数组将POSTSubmitExpenses操作:

 var checkedArray = []; $(':checkbox[name=isSubmitted]').on('change', function () { checkedArray = $(':checkbox[name=isSubmitted]:checked').map(function () { return this.id; }) .get(); //alert(checkedArray); }); $('#submitExpensesLink').click(function () { $.ajax({ type: "POST", traditional: true, url: "@Url.Action("SubmitExpenses", "Expenses")", data: { expenseIDs: checkedArray }, success: function () { alert("Success!"); }, error: function (XMLHttpRequest, textStatus, errorThrown) { if (debug) { alert(XMLHttpRequest.responseText); alert(textStatus); alert(errorThrown); } } }); }) 

1)将FormMethod.Post添加到@using (Html.BeginForm()) {}

 @using (Html.BeginForm("nameAction", "nameController", FormMethod.Post)) { //Your code } 

2)你应该为这样的输入添加名称: