首页 > 解决方案 > 将 JavaScript 对象数组传递给控制器

问题描述

我有一个需要提交给我的控制器的动态表单。ajax在构建我的 Javascript 对象数组后,我正在尝试使用请求来执行此操作。当我尝试只string向控制器发送一个值时,我的模型一直是null. 但是,当我尝试发送我的 Javascriptarray时,我收到了400 (Bad Request)回复。

我的动态表单是用来创建一个整体的Ticket. 它TicketEntries最终用户组成,因为他们能够向表单表添加新行。表单的输入:AccountNumber, AccountDescription, DebitAmount, CreditAmount, PostingDescription, PostDate.

表格table

@model Areas.TicketEntry.Models.FormTicketSubmissionModel
...
<div class="postDate">
    <label asp-for="PostDate" class="control-label"></label>
    <input id="PostDateInput" autocomplete="off" />
    <span asp-validation-for="PostDate" class="text-danger"></span>
</div>

<form action="Create" method="post" class="ticketForm">
    <div class="ticketTable">
        <table class="table" id="inputTable">
            <thead>
                <tr>
                    <th>
                        @Html.DisplayNameFor(model => model.AccountNumber)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.AccountDescription)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.DebitAmount)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.CreditAmount)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.PostingDescription)
                    </th>
                    <th>
                        <input type="checkbox" id="checkAllCheckBox" class="allRowCheckBox" value="all" />
                    </th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < 2; i++)
                {
                    <tr>
                        <td class="tableAccountNumber">
                            <input id="@($"form{i}AccountInfo")" list="AccountList" class="AccountInfo">
                        </td>
                        <td class="tableAccountDescription">
                            <input id="@($"form{i}AccountDescription")" class="AccountDescription" />
                            <span asp-validation-for="AccountDescription" class="text-danger"></span>
                        </td>
                        <td class="tableDebitAmount">
                            <input type="text" data-type="currency" id="@($"form{i}DebitAmount")" class="debitAmount" asp-for="DebitAmount" asp-format="{0:C}" value="0.00" />
                            <span asp-validation-for="DebitAmount" class="text-danger"></span>
                        </td>
                        <td class="tableCreditAmount">
                            <input type="text" data-type="currency" id="@($"form{i}CreditAmount")" class="creditAmount" asp-for="CreditAmount" asp-format="{0:C}" value="0.00" />
                            <span asp-validation-for="CreditAmount" class="text-danger"></span>
                        </td>
                        <td class="tablePostingDescription">
                            <input type="text" id="@($"form{i}PostingDescription")" class="postDescrip" value="" />
                            <span asp-validation-for="PostingDescription" class="text-danger"></span>
                        </td>
                        <td class="tableSelectBox">
                            <input type="checkbox" id="@($"form{i}CheckBox")" class="rowCheckBox" value="selected" />
                        </td>
                    </tr>
                }
            </tbody>
        </table>
        <div class="tableModifyButtons">
            <button id="addRow" type="button">Add Row</button>
            <button id="deleteRow" type="button">Delete Row</button>
        </div>
    </div>

    <div class="formButtons">
        <button id="submitButton" type="button" class="btn btn-primary">Submit Ticket</button>
    </div>
</form>

我的 Javascript 是由我#submitButton被点击触发的。这将迭代 的 Id#inputTable并将行值添加到并返回一个array。我可以将array对象打印到控制台,并且所有值都符合预期。我目前正在尝试对数组进行字符串化,JSON以将其传递给我的控制器。

我用于提交表单的 Javascript:

// Function for submitting data to controller
function submitTickets() {
    // Iterate through table and generate type array for ticket submission
    // - Add to array of tickets
    // - using JSON and stringify it
    // - Pass to controller with AJAX

    let tickets = getTableTickets('inputTable');
    
    let authToken = $('input[name="__RequestVerificationToken"]');

    if (!validateTickets(tickets)) {
        setWarningMessage('Invalid Ticket Entries detected. Please review your entries and try again.', 'block');
        return;
    }

    let jsonTickets = JSON.stringify({ "tickets": tickets });

    // Ajax it to server
    // How to send JSON to server?
    $.ajax({
        url: "/TicketEntry/Tickets/Create",
        type: "POST",
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        traditional: true,
        data: {
            __RequestVerificationToken: authToken,
            model: jsonTickets
        },
        success: function (data, textStatus, jqXHR) {
            setMessage('SUCCESS: ' + data.Message, 'block');
        },
        error: function (jqXHR, textStatus, errorThrown) {
            setWarningMessage('Error: ' + jqXHR.statusText + ' - ' + textStatus + ' - ' + errorThrown, 'block');
        }
    });

    console.log(jsonTickets);
    console.log('ticket input length: ' + tickets.length);
}

JSON.Stringified数组输出:

{"model":[{"AccountNumber":"0000000","AccountDescription":"TEST ACCOUNT","DebitAmount":"25.00","CreditAmount":"0.00","PostingDescription":"TEST","PostDate":"07/15/2021"},{"AccountNumber":"0000001","AccountDescription":"TEST ACCOUNT 2","DebitAmount":"25.00","CreditAmount":"0.00","PostingDescription":"TEST","PostDate":"07/15/2021"},{"AccountNumber":"0000002","AccountDescription":"TEST ACCOUNT 3","DebitAmount":"0.00","CreditAmount":"50.00","PostingDescription":"TEST","PostDate":"07/15/2021"}]}

我当前的视图模型:

public class FormTicketSubmissionModel
    {
        [Display(Name = "Account Number")]
        public string AccountNumber { get; set; }

        [DataType(DataType.Text)]
        [StringLength(29, ErrorMessage = "Description is too long!")]
        [RegularExpression(@"^[a-zA-Z0-9+&.""/'\s-]*$")]
        [Display(Name = "Account Description")]
        public string AccountDescription { get; set; }

        [Display(Name = "Posting Description")]
        [StringLength(29, ErrorMessage = "Posting Description is too long!")]
        [RegularExpression(@"^[a-zA-Z0-9+&.""/'\s-]*$")]
        public string PostingDescription { get; set; }

        [Display(Name = "Post Date")]
        [DataType(DataType.Date)]
        public DateTime PostDate { get; set; }

        [Display(Name = "Debit Amount")]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18,2)")]
        [Required]
        public decimal DebitAmount { get; set; } = 0.00m;

        [Display(Name = "Credit Amount")]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18,2)")]
        [Required]
        public decimal CreditAmount { get; set; } = 0.00m;
    }

我尝试使用我的 Ajax 仅传递字符串值,但我的模型始终是null. 这是我当前的操作方法:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([FromBody]List<FormTicketSubmissionModel> model)
{
    if (ModelState.IsValid)
    {
        // Validate data within models and save them to database 
        // ...
        
        return RedirectToAction(nameof(Index));
    }
    
    return View(model);
}

如何将对象数组从 Javascript 传递给我的控制器?

预先感谢您的任何帮助!

标签: javascriptc#ajaxasp.net-core

解决方案


重新访问@Llama 的共享链接后,我重新设计了我的模型和表格。此外,在我的视图表单中,我有<form action="Create" .../>而不是<form asp-action="Create" .../>. 这导致我的表单提交以400. 我的解决方案不再需要JavaScript/ Ajax

新型号:

    public class FormTicketSubmissionModel
    {
        [HiddenInput]
        public int Id { get; set; }

        // Stores the values of the entries 
        public FormTicketEntryModel[] TicketEntries { get; set; }

        [Display(Name = "Post Date")]
        [DataType(DataType.Date)]
        public DateTime PostDate { get; set; }

        [DataType(DataType.Text)]
        [RegularExpression(@"^[a-zA-Z0-9]*$")]
        public string UserName { get; set; }
    }

    public class FormTicketEntryModel
    {
        [HiddenInput]
        public int Id { get; set; }

        [Display(Name = "Account Number")]
        public string AccountNumber { get; set; }

        [DataType(DataType.Text)]
        [StringLength(29, ErrorMessage = "Description is too long!")]
        [RegularExpression(@"^[a-zA-Z0-9+&.""/'\s-]*$")]
        [Display(Name = "Account Description")]
        public string AccountDescription { get; set; }

        [Display(Name = "Posting Description")]
        [StringLength(29, ErrorMessage = "Posting Description is too long!")]
        [RegularExpression(@"^[a-zA-Z0-9+&.""/'\s-]*$")]
        public string PostingDescription { get; set; }

        [Display(Name = "Debit Amount")]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18,2)")]
        [Required]
        public decimal DebitAmount { get; set; } = 0.00m;

        [Display(Name = "Credit Amount")]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18,2)")]
        [Required]
        public decimal CreditAmount { get; set; } = 0.00m;
    }

我的新观点:

<form asp-action="Create" method="post" class="ticketForm">
    <input asp-for="Id" />
    <div class="ticketTable">
        <table class="table" id="inputTable">
            <thead>
                <tr>
                    <th>
                        <label>Account Number</label>
                    </th>
                    <th>
                        <label>Account Description</label>
                    </th>
                    <th>
                        <label>Debit Amount</label>
                    </th>
                    <th>
                        <label>Credit Amount</label>
                    </th>
                    <th>
                        <label>Posting Description</label>
                    </th>
                    <th>
                        <input type="checkbox" id="checkAllCheckBox" class="allRowCheckBox" value="all" />
                    </th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < 2; i++)
                {
                    <tr>
                        <td class="tableAccountNumber">
                            <input id="@($"form{i}AccountInfo")" asp-for="@Model.TicketEntries[i].AccountNumber" list="AccountList" class="AccountInfo">
                        </td>
                        <td class="tableAccountDescription">
                            <input id="@($"form{i}AccountDescription")" asp-for="@Model.TicketEntries[i].AccountDescription" class="AccountDescription" />
                            <span asp-validation-for="@Model.TicketEntries[i].AccountDescription" class="text-danger"></span>
                        </td>
                        <td class="tableDebitAmount">
                            <input type="text" data-type="currency" id="@($"form{i}DebitAmount")" class="debitAmount" asp-for="@Model.TicketEntries[i].DebitAmount" asp-format="{0:C}" value="0.00" />
                            <span asp-validation-for="@Model.TicketEntries[i].DebitAmount" class="text-danger"></span>
                        </td>
                        <td class="tableCreditAmount">
                            <input type="text" data-type="currency" id="@($"form{i}CreditAmount")" class="creditAmount" asp-for="@Model.TicketEntries[i].CreditAmount" asp-format="{0:C}" value="0.00" />
                            <span asp-validation-for="@Model.TicketEntries[i].CreditAmount" class="text-danger"></span>
                        </td>
                        <td class="tablePostingDescription">
                            <input type="text" id="@($"form{i}PostingDescription")" asp-for="@Model.TicketEntries[i].PostingDescription" class="postDescrip" value="" />
                            <span asp-validation-for="@Model.TicketEntries[i].PostingDescription" class="text-danger"></span>
                        </td>
                        <td class="tableSelectBox">
                            <input type="checkbox" id="@($"form{i}CheckBox")" class="rowCheckBox" value="selected" />
                        </td>
                    </tr>
                }
            </tbody>
        </table>
        <div class="tableModifyButtons">
            <button id="addRow" type="button">Add Row</button>
            <button id="deleteRow" type="button">Delete Row</button>
        </div>
    </div>

    <div class="formButtons">
        <button id="submitButton" type="submit" class="btn btn-primary">Submit Ticket</button>
    </div>
</form>

推荐阅读