为什么我的视图模型数据不基于我的 .NET Core 应用程序中的控制器

Why is my view model data not being based to controller in my .NET Core App

我有一个 update/edit 表单,我在其中使用视图模型和数据绑定。当我提交此 update/edit 表单时,没有数据基于控制器。模型为 null,id 值为 0(它应该是一个值)。我不确定这里出了什么问题。我在表单中使用帮助标签。我的控制器正在使用 [FromForm]。我做错了什么?

视图如下:

  @model ITODashboard.ViewModels.AddorEditViewModel

@{
    ViewData["Title"] = Model.Order.Id == 0 ? "Create ITO" : Model.Order.ITO;
}

<form method="post" asp-action="AddOrEdit" asp-controller="AddorEdit" enctype=multipart/form-data id="orderForm">
    <input asp-for="Order.Id" name="_orderId" id="orderId" hidden />
    <input asp-for="Order.AuthorEDIPI" name="_authorEDIPI" id="authorEDIPI" hidden />
    <input asp-for="Order.EditorEDIPI" name="_authorEDIPI" id="authorEDIPI" hidden />
    <div class="p-3">
        @*<div asp-validation-summary="ModelOnly" class="text-danger"></div>*@
        <div class="form-group row">
            <h1>@ViewData["Title"]</h1>
        </div>
        <hr />
        <div class="row">
            <div class="col-sm-6">
                <!--Title, Status, Name section-->
                <div class="form-group row">
                    <div class="col-sm-6">
                        <label asp-for="Order.ITO">
                            ITO #: <b style="color: red;">*</b>
                        </label>
                        <input asp-for="Order.ITO" class="form-control input-sm" id="itoTitle" required autofocus>
                    </div>

                    <div class="col-sm">
                        <label asp-for="Order.StatusId">
                            <a href="#" data-toggle="tooltip" title="ITO status is determined by the task(s) status.">
                                <i class="fas fa-info-circle" aria-hidden="true" tabindex="-1"></i>
                            </a> Status:
                        </label>
                        <div>
                            <select asp-for="Order.StatusId" asp-items="@ViewBag.StatusDropDown" class="form-control"
                                    id="itoStatus" required disabled>
                                <option value=""></option>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-sm-12">
                        <label asp-for="Order.ItoName">Title: </label>
                        <input asp-for="Order.ItoName" class="form-control" id="itoName">
                    </div>
                </div>
                <!--Notes section-->
                @*Hide Notes Section till ITO is created*@
                @if (Model.Order.Id > 0)
                {
                    <div class="form-group row" id="itoNotesSection">
                        <div class="col-sm">
                            <label class="float-left m-1" for="itoNotes">Notes:</label>
                            <a class="btn float-right" data-toggle="tooltip" title="Click to expand note area." id="expandOrderNote"><i class="fa-solid fa-expand"></i> Expand</a>

                            <a class="btn float-right" data-toggle="tooltip" title="Click to add a new note." id="openOrderNote"><i class="fa-solid fa-plus"></i> New</a>
                            <br />

                            <div class="form-control notes-list text-break mt-2" id="itoNotesCtn">

                                @foreach (var note in Model.OrderNotes)
                                {

                                    <li id=@note.Id style="list-style: none;">
                                        <div class="ito-notes-header text-dark" style="display: flex; justify-content: center;">
                                            <div class="ito-notes-date text-dark" style="justify-content: center;">@note.Modified.ToString("dd/MM/yyyy")</div>
                                            <div hidden id="noteCreatedDt">@note.Created</div>
                                            <div class="ito-notes-name text-dark" style="justify-content: center;">@note.Author</div>
                                            <div class="ito-notes-category text-danger" style="justify-content: center;"><span id="orderCategory" hidden>@note.NoteCategoryId</span> <span>@note.Category</span><span><a class="btn text-dark" data-toggle="tooltip" title="Click to edit a note." id="btnEditNote"><i class="fa-solid fa-pen-to-square"></i> Edit</a></span> </div>
                                        </div>
                                        @{
                                            string noteId = "orderNote" + @note.Id;
                                        }
                                        <div class="ito-note text-dark" id=@noteId>@note.Note</div>
                                    </li>
                                }
                            </div>
                        </div>
                    </div>
                }
                <!--Network & Source sections-->
                <div class="form-group row">
                    <div class="col-sm">
                        <label asp-for="Order.NetworkId">Network: <b style="color: red;">*</b></label>
                        <div>
                            <select asp-for="Order.NetworkId" asp-items="@ViewBag.NetworkDropDown" class="form-control"
                                    id="itoNetwork" required>
                                <option value="">Choose...</option>
                            </select>
                        </div>
                    </div>
                    <div class="col-sm">
                        <label asp-for="Order.SourceId">Source: <b style="color: red;">*</b></label>
                        <div>
                            <select asp-for="Order.SourceId" asp-items="@ViewBag.SourceDropDown" class="form-control" id="itoSource"
                                    required>
                                <option value="">Choose...</option>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-sm">
                        <!--Dates section-->
                        <div class="form-group row">
                            <label asp-for="Order.Received" class="col-sm-4">Received:</label>
                            <div class="col-sm-8">
                                <div class="input-append date">
                                    @if (Model.Order.Id > 0)
                                    {
                                        <input asp-for="Order.Received" type="date" class="form-control input-sm" id="itoReceivedDt" placeholder="MM/DD/YYYY" disabled>
                                    }
                                    else
                                    {
                                        <input asp-for="Order.Received" type="date" class="form-control input-sm" id="itoReceivedDt" placeholder="MM/DD/YYYY">
                                    }
                                </div>
                            </div>
                        </div>
                        <div class="form-group row">
                            <label asp-for="Order.Suspense" tabindex="-1" class="col-sm-4">
                                <a href="#" data-toggle="tooltip" title="Determined by the earliest task suspense date.">
                                    <i class="fas fa-info-circle" aria-hidden="true" tabindex="-1"></i>
                                </a>
                                Suspense:
                            </label>
                            <div class="col-sm-8">
                                @if (Model.Order.Id > 0)
                                {
                                    <input asp-for="Order.Suspense" type="date" class="form-control input-sm" id="itoSuspenseDt" placeholder="MM/DD/YYYY" disabled>
                                }
                                else
                                {
                                    <input asp-for="Order.Suspense" type="date" class="form-control input-sm" id="itoSuspenseDt" placeholder="MM/DD/YYYY">
                                }
                            </div>
                        </div>
                    </div>
                    <div class="col-sm">
                        <div class="form-group row">
                            <label asp-for="Order.Release" tabindex="-1" class="col-sm-4">Release: </label>
                            <div class="col-sm-8">
                                @if (Model.Order.Id > 0)
                                {
                                    <input asp-for="Order.Release" type="date" class="form-control input-sm" id="itoReleaseDt" placeholder="MM/DD/YYYY" disabled>
                                }
                                else
                                {
                                    <input asp-for="Order.Release" type="date" class="form-control input-sm" id="itoReleaseDt" placeholder="MM/DD/YYYY">
                                }
                            </div>
                        </div>
                        <div class="form-group row">
                            <label asp-for="Order.Completed" tabindex="-1" class="col-sm-4">Completed: </label>
                            <div class="col-sm-8">
                                @if (Model.Order.Id > 0)
                                {
                                    <input asp-for="Order.Completed" type="date" class="form-control input-sm" id="itoCompletedDt" placeholder="MM/DD/YYYY" disabled>
                                }
                                else
                                {
                                    <input asp-for="Order.Completed" type="date" class="form-control input-sm" id="itoCompletedDt" placeholder="MM/DD/YYYY">
                                }
                            </div>
                        </div>
                    </div>
                </div>
                <!--Details and documents section-->
                <div class="form-group row">
                    <div class="col-sm">
                        <label asp-for="Order.Details">Details: </label>
                        <textarea asp-for="Order.Details" class="form-control" id="itoDetails" rows="5"></textarea>
                    </div>
                </div>
            </div>
            <div class="col-sm-6">
                <div class="form-group row">
                    <div class="col-sm">
                        <div class="bg-secondary text-white rounded" style="padding:5px; font-size: 18px; font-weight: bold;">
                            Team
                            Selector
                        </div>
                    </div>
                    <div class="col-sm">
                        <div class="bg-secondary text-white border border-secondary rounded"
                             style="padding:5px; font-size: 18px; font-weight: bold;">
                            Service Managers<span id="editSvcManager" class="float-right" style="width:100px"
                                                  onclick="openSvcMgrEditor()">
                                <i class="fa fa-user" data-toggle="tooltip" title="Edit Owners and Team assignments">
                                    Edit
                                </i>
                            </span>
                        </div>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-sm teams-scrollable">
                        <div id="organizationSelectorCtn">
                            <ul class="bulletless" id="organizationSelector">
                                @*Populated via AJAX call*@
                            </ul>
                        </div>
                    </div>
                    <div class="col-sm teams-scrollable">
                        <ul id="divSvcMgrContainer"></ul>
                    </div>
                </div>
                @if (Model.Order.Id > 0)
                {
                    <div class="form-group row" id="itoTasksHeaderRow">
                        <div class="col-sm">
                            <div class="bg-secondary text-white rounded" style="padding:5px; font-size: 18px; font-weight: bold;">
                                Tasks<i class="fa fa-plus plusIcon float-right" onclick="openNewTask()" id="plusTask"
                                        data-toggle="tooltip" title="Create a new task" style="cursor: pointer;"> New</i>
                                <!-- <i class="far fa-check-circle float-right" style="margin-right: 20px; cursor: pointer;"
                                id="viewAllTasks" title="View all tasks for this ITO." onClick="popluateAllTasks()">
                                View All</i> -->
                            </div>
                        </div>
                    </div>
                    <div class="form-group row" id="itoTasksRow">
                        <div class="col-sm">
                            <div id="taskListContainer">
                                @*Populated via AJAX call*@
                            </div>
                        </div>
                    </div>
                }

                @if (Model.Order.Id > 0)
                {
                    <div class="form-group row" id="itoDocsRow">
                        <div class="col-sm">
                            <div class="bg-secondary text-white rounded collapsed" id="doc-header"
                                 style="padding:5px; font-size: 18px; font-weight: bold;" data-toggle="collapse"
                                 data-target="#txtfileContainer" aria-expanded="false" aria-controls="txtfileContainer">
                                <a href="#" data-toggle="tooltip" title="Click header to expand Documents section.">
                                    <i class="fas fa-info-circle text-white" aria-hidden="true" tabindex="-1"></i>
                                </a>
                                Supporting
                                Documents
                                @*<i class="fa fa-plus plusIcon float-right" id="plusDoc" data-toggle="tooltip" title="Add Documents"
                                    style="cursor: pointer;"> Add</i><input asp-for="Files" type="file" class="custom-file-input" id="formFile">*@

                            </div>
                            <div id="txtfileContainer" class="collapse scrollable">
                                @*<div id="docDropNote" class="droptarget">
                                        (Drag & Drop documents here)
                                    </div>*@
                                <label>Upload File(s)</label>
                                <input asp-for="Files" type="file" name="FormFile" id="FormFile" multiple />

                                <br>

                                @foreach (var item in Model.Files)
                                {
                                    <table class="table table-bordered" id="documentTable">
                                        <tr class="bg-light">
                                            <th class="col-md-6 bg-light">
                                                Document Name
                                            </th>
                                            <th class="col-md-2 bg-light">
                                                Uploaded
                                            </th>
                                            <th class="col-md-2 bg-light">Author</th>
                                            <th class="col-md-2 bg-light"></th>
                                        </tr>

                                        <tr>
                                            <td>
                                                <a asp-area="" asp-controller="AddorEdit" asp-route-id="@item.Id" asp-action="Download">@item.FileName</a>
                                            </td>

                                            <td>
                                                @*@item.Created*@
                                            </td>

                                            <td>
                                                @*@item.Author*@
                                            </td>
                                            <td width="5%">
                                                <div class="w-100">
                                                    <a class="mx-1" asp-controller="Home" asp-route-Id="@item.Id" asp-action="DocumentDelete"><i class="fas fa-trash-alt text-danger"></i></a>
                                                </div>

                                            </td>
                                        </tr>
                                    </table>
                                }
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
    </div>
    <div class="form-group row">
        <div class="col-8 offset-3 row">
            <div class="col">
                <input type="submit" class="btn btn-success w-50" value="Create" data-toggle="tooltip"
                        title="Save this ITO and close form." />
            </div>
            <div class="col">
                <a asp-action="Index" class="btn btn-danger w-50">Back</a>
            </div>
        </div>
    </div>
</form>

这里是控制器:

 // POST: AddorEdit/Id?   
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult AddOrEdit([FromForm] int id, [Bind("ITO,ItoName,Received,Suspense,Release,Completed,StatusId,NetworkId,SourceId,Details,Released,EditorEDIPI,Editor,AuthorEDIPI,Author")] AddorEditViewModel addorEditViewModel)
        {

            if (ModelState.IsValid)
            {
                int newId = 0;

                using (SqlConnection sqlConnection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
                {
                    sqlConnection.Open();
                    SqlCommand sqlCmd = new SqlCommand("BookAddOrEdit", sqlConnection);
                    sqlCmd.CommandType = CommandType.StoredProcedure;                   
                    sqlCmd.Parameters.AddWithValue("ITO", addorEditViewModel.Order.ITO);
                    sqlCmd.Parameters.AddWithValue("ItoName", addorEditViewModel.Order.ItoName);
                    sqlCmd.Parameters.AddWithValue("Received", addorEditViewModel.Order.Received);
                    sqlCmd.Parameters.AddWithValue("Suspense", addorEditViewModel.Order.Suspense);
                    sqlCmd.Parameters.AddWithValue("Release", addorEditViewModel.Order.Release);
                    sqlCmd.Parameters.AddWithValue("Completed", addorEditViewModel.Order.Completed);
                    sqlCmd.Parameters.AddWithValue("StatusId", addorEditViewModel.Order.StatusId);
                    sqlCmd.Parameters.AddWithValue("NetworkId", addorEditViewModel.Order.NetworkId);
                    sqlCmd.Parameters.AddWithValue("SourceId", addorEditViewModel.Order.SourceId);
                    sqlCmd.Parameters.AddWithValue("Details", addorEditViewModel.Order.Details);
                    sqlCmd.Parameters.AddWithValue("Released", addorEditViewModel.Order.Released);
                  

                    if(addorEditViewModel.Order.Id == 0)
                    {
                        sqlCmd.Parameters.AddWithValue("Created", new DateTime());
                        sqlCmd.Parameters.AddWithValue("Modified", new DateTime());
                        sqlCmd.Parameters.AddWithValue("AuthorEDIPI", addorEditViewModel.Order.AuthorEDIPI);
                        sqlCmd.Parameters.AddWithValue("Author", addorEditViewModel.Order.Author);
                        sqlCmd.Parameters.AddWithValue("EditorEDIPI", addorEditViewModel.Order.EditorEDIPI);
                        sqlCmd.Parameters.AddWithValue("Editor", addorEditViewModel.Order.Editor);
                    }
                    else
                    {
                        sqlCmd.Parameters.AddWithValue("EditorEDIPI", addorEditViewModel.Order.EditorEDIPI);
                        sqlCmd.Parameters.AddWithValue("Editor", addorEditViewModel.Order.Editor);
                        sqlCmd.Parameters.AddWithValue("Modified", new DateTime());
                    }
                   

                    sqlCmd.ExecuteNonQuery();

                    newId = Convert.ToInt32(sqlCmd.ExecuteScalar());                    
                }

                //Loop through any/all the documents and upload
                if (addorEditViewModel.Files != null)
                {
                    foreach (IFormFile doc in addorEditViewModel.Files)
                    {
                        //Getting FileName
                        var fileName = Path.GetFileName(doc.FileName);
                        //Getting file Extension
                        var fileExtension = Path.GetExtension(fileName);                                    

                        var objfiles = new Files()
                        {
                            Id = 0,
                            FileName = fileName,
                            FileType = fileExtension,
                            OrderId = newId,
                            Author = "Breymaier, Ashley E CTR USARMY RCC-C (USA)",
                            AuthorEDIPI = 1042123982,
                            Created = new DateTime()
                        };

                        using (var target = new MemoryStream())
                        {
                            doc.CopyTo(target);
                            objfiles.DataFile = target.ToArray();
                        }

                        using (SqlConnection sqlConnection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
                        {
                            sqlConnection.Open();
                            SqlCommand sqlCmd = new SqlCommand("UploadOrderDocument", sqlConnection);
                            sqlCmd.CommandType = CommandType.StoredProcedure;
                            sqlCmd.Parameters.AddWithValue("Id", objfiles.Id);
                            sqlCmd.Parameters.AddWithValue("FileName", objfiles.FileName);
                            sqlCmd.Parameters.AddWithValue("FileType", objfiles.FileType);
                            sqlCmd.Parameters.AddWithValue("OrderId", objfiles.OrderId);
                            sqlCmd.Parameters.AddWithValue("Author", objfiles.Author);
                            sqlCmd.Parameters.AddWithValue("AuthorEDIPI", objfiles.AuthorEDIPI);
                            sqlCmd.Parameters.AddWithValue("Created", objfiles.Created);

                            sqlCmd.ExecuteNonQuery();
                           
                        }
                    }

                }


                return RedirectToAction(nameof(Index));
            }
            return View();
}

这是视图模型:

    public class AddorEditViewModel
    {
        public Order Order { get; set; }
        public List<Models.Task> Tasks { get; set; }
        public List<Response> Responses { get; set; }
        public List<TaskNote> TaskNotes { get; set; }
        public List<OrderNote> OrderNotes { get; set; }     
        public List<IFormFile> UploadFiles { get; set; }
        public List<Files> Files { get; set; }
    }
}

首先用助手替换你的表单标签,用控制器名称替换控制器,而不是动作(就像你的那样)并添加@Html.AntiForgeryToken()

@using (Html.BeginForm("AddOrEdit", "Controller",  FormMethod.Post))
{
    @Html.AntiForgeryToken()

....

并清理动作

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult AddOrEdit(AddorEditViewModel addorEditViewModel)

我在为存储 id 值的隐藏输入元素使用名称 属性、name="_orderId" 时遇到的问题。一旦我删除了名称 属性、name="_orderId",id 就按预期出现了。