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

问题描述:

我试图通过多个项目类型列表 <项目>我的控制,但是,当我提出我的数据,它在我的控制器中显示为空。如何通过项目列表从视图到控制器(ASP.NET MVC 4)

我想发生这样的是,我有在视图“费”的列表,每个“费用”或项目旁边是我的模型中提交布尔属性的复选框。当我检查项目时,我想要检查项目的属性列表提交日期提交要在数据库中更新。

@ Html.DisplayFor(modelItem => item.Submitted)在视图中产生复选框。

我在做什么错?

这是我的观点:

@model IEnumerable<Expenses.Models.Expense> 

@{ 
ViewBag.Title = "Submit Expenses"; 
Layout = "~/Views/Shared/_Layout.cshtml"; 

DateTime today = DateTime.Today; 
string formattedDate = today.ToString("MM/dd/yyyy"); 
} 

<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> 
<script src="//code.jquery.com/jquery-1.10.2.js"></script> 
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> 

<h2>Submit Expenses</h2> 

@using (Html.BeginForm()) 
{ 
@Html.AntiForgeryToken() 
<div class="form-inline"> 
    <div class="form-group"> 
     <h4>Start Date:</h4> 
     <div class="col-md-10"> 
      @Html.TextBox("expenseDate", formattedDate, htmlAttributes: new 
      { 
       @class = "form-control" 
      }) 
     </div> 
    </div> 

    <div class="form-group"> 
     <h4>End Date:</h4> 
     <div class="col-md-10"> 
      @Html.TextBox("expenseDate2", formattedDate, htmlAttributes: new 
      { 
       @class = "form-control" 
      }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @if (User.IsInRole("admin")) 
     { 
      <h4>Username:</h4> 
      <div class="editor-field"> 
       @Html.DropDownList("UserId", String.Empty) 
      </div> 
     } 
    </div> 

    <br /> 
    <br /> 

    <div class="form-group"> 
     <div class="col-md-2"> 
      <input type="submit" value="Retrieve Expenses" class="btn btn-default" /> 
     </div> 
    </div> 

</div> 

<br /> 
<br /> 


<p> 
    @Html.ActionLink("Create New", "Create") 
</p> 
<table style="margin-bottom: 20px;"> 
    <tr> 
     <th> 
      @Html.DisplayNameFor(model => model.Company) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.Category) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.Province) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.ReceiptName) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.Comment) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.GrossAmount) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.TaxAmount) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.NetAmount) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.Mileage) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.TravelStatus) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.LunchLearnStatus) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.WithClientStatus) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.DateEntered) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.DateSubmitted) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.ExpenseDate) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.ImageName) 
     </th> 
     @if (User.IsInRole("admin")) 
     { 
      <th> 
       @Html.DisplayNameFor(model => model.UserProfile.UserName) 
      </th> 
     } 
     <th></th> 
    </tr> 
    <tr> 
     <td> 
      <b>Select All:</b> 
      <br /> 
      <input type="checkbox" name="expense" value="Expense" id="selectAllCheckboxes" class="expenseCheck"> 
     </td> 
    </tr> 
    @foreach (var item in Model) 
    { 
     <tr> 
      <td class="submitCheck"> 
       @Html.EditorFor(modelItem => item.Submitted) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Company) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Category) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Province) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.ReceiptName) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Comment) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.GrossAmount) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.TaxAmount) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.NetAmount) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.Mileage) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.TravelStatus) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.LunchLearnStatus) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.WithClientStatus) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.DateEntered) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.DateSubmitted) 
      </td> 
      <td> 
       @Html.DisplayFor(modelItem => item.ExpenseDate) 
      </td> 
      <td> 
       @if (item.ImageName != null) 
       { 
        <a href="~/Images/@Html.DisplayFor(modelItem => item.UserProfile.FullName)/@Html.DisplayFor(modelItem => item.ImageName)" class="imageClick" target="_blank"><img src="~/Images/@Html.DisplayFor(modelItem => item.UserProfile.FullName)/@Html.DisplayFor(modelItem => item.ImageName)" alt="Image" style="width:80%" /></a> 
       } 
      </td> 
      @if (User.IsInRole("admin")) 
      { 
       <td> 
        @Html.DisplayFor(modelItem => item.UserProfile.UserName) 
       </td> 
      } 
      <td> 
       @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 }) 
       } 

      </td> 
     </tr> 
    } 

</table> 

@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;"}) 

<div class="ExportSection" style="margin-top:30px;"> 
    @*<a href="javascript:void(0)">Export To CSV</a>*@ 
    @Html.ActionLink("Export To CSV", "ExportExpensesListToCSV") 
</div> 
} 

@section scripts { 
<script type="text/javascript"> 


    $("#selectAllCheckboxes").click(function() { 
     $('.submitCheck input:checkbox').not(this).prop('checked', this.checked); 
    }); 

    $(function() { 
     $("#expenseDate").datepicker(); 
    }); 

    $(function() { 
     $("#expenseDate2").datepicker(); 
    }); 

</script> 

} 

,这里是我的控制器方法:

public ActionResult SubmitExpenses(List<Expense> 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 <= 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 expensesFromView = expenses; 

     var joined = from dbExpense in query.Select(x => x.e).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被显示为空,因此,我在我的joined查询中收到错误消息:

值不能为空。参数名:内

我无法真正找到一种方法将视图直接从View传递给Controller,所以我决定使用AJAX。

我改变控制器的参数从类型列表<>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 => x.e).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到它的ID是自己的HTML复选框:

@foreach (var item in Model) 
    { 
     <tr> 
      <td class="checkbox-td"> 
       @Html.CheckBox("isSubmitted", new 
      { 
       @id = @Html.DisplayFor(modelItem => item.ExpenseId), 
       @class = "submitBox" 
      }) 
      </td> 
     </tr> 
    } 

<div> 
    @Html.ActionLink("Submit Expenses", "", "", null, new { @id = "submitExpensesLink" }) 
</div> 

我写了一些jQuery的,使每个被选中的复选框,将输入元素的ID添加到阵列和ARRA整数Ÿ将POST方法SubmitExpenses行动:

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),你应该为输入添加名字是这样的:

<input type="text" name="someName"/> 
+0

谢谢您的回答。我试过了,数据仍然没有正确传递。 – Sicypher

+0

@ bkhosh2,我编辑了我的解决方案 – praguan

有两种方式这样做 -

1。

您可能需要这种扩展是非常好,extensible- MvcCheckBoxList - 看来这个网站已被关闭:)参考选项2

2。

@for (int i = 0; i < Model.Count; i++) 
{ 
    <tr> 
     <td class="submitCheck"> 
     <input type="checkbox" value="@Model[i].Id" name="Expense[@i].Id"> 
     <input type="hidden" value="0" name="Expense[@i].Id">   
     </td> 
     <td> 
       @Html.DisplayFor(modelItem => item.Company) 
     </td> 

btw:如果您使用第二种方法:在您的控制器中,筛选费用对象ID的零值;如果没有选择,则向控制器发送零(作为元素的ID)宽限于您可以在上面的代码中看到的“隐藏”字段。

+0

谢谢你。你给我的链接似乎是我需要的。我会试试这个,让你知道它是否有效! – Sicypher

+0

想知道为什么这没有为你工作。在您的控制器操作中,您应该使用提交的值接收int []。不要忘记只采用Id值大于0的项目 –