小编典典

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

ajax

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

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

视图中的@ 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>

}

这是我的Controller方法:

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显示为null,结果,我的joined查询出现错误,提示:

值不能为空。 参数名称:内部


阅读 248

收藏
2020-07-26

共1个答案

小编典典

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

我将控制器的参数从 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 => 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分配给它自己的HTML复选框的ID:

@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添加到数组中,并且整数数组将被过 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);
            }
        }
    });
    })
2020-07-26