【发布时间】:2017-01-04 19:15:59
【问题描述】:
场景: 我有一个表,其中包含从 ViewModel 填充的行。每行都有复选框,允许用户检查 1 行或多行,然后从下拉菜单中的操作中进行选择,以对所选行的属性进行编辑。
到目前为止一切正常,我可以让 ViewModel 正确传递,然后在 POST Action 方法中使用它以及它的所有属性。我可以根据用户选择的选项进行更改。
但是,由于下拉列表中的某些选项会产生相当大且不可逆的更改,因此我正在使用 GET 调用新视图并仅使用选定的行填充新表,并要求用户确认他们想要做出改变。到目前为止,一切都还不错。新视图会按预期填充之前视图中选择的行。
问题: 在用户确认他们的意图后,使用 POST 调用 Action 方法。正确填充当前视图的 ViewModel 正在正确地进入控制器。我得到了 ViewModel,但与填充 View 的属性不同。
视图模型
public class ProjectIndexViewModel
{
public List<ProjectDetailsViewModel> Projects { get; set; }
public string FlagFormEditProjects { get; set; }
public string FlagFormNewProjectStatus { get; set; }
}
List<ProjectDetailsViewModel> Projects 用于填充表中的行,而 Projects 是在控制器的 POST Action 方法中未正确绑定的。
选中复选框的初始视图。注意选择下拉选项之一时调用的 JavaScript 函数之一的示例,这是提交表单的内容。
@using (Html.BeginForm("EditProjectsTable", "Project", FormMethod.Get, new { name = "formEditProjects", id = "formEditProjects" }))
{
@Html.HiddenFor(item => item.FlagFormEditProjects)
@Html.HiddenFor(item => item.FlagFormNewProjectStatus)
....
<table>
<thead>
....
</thead>
<tbody>
@for (int i = 0; i < Model.Projects.Count; i++)
{
<tr>
<td>@Html.DisplayFor(x => x.Projects[i].ProjectNumber)</td>
<td>@Html.DisplayFor(x => x.Projects[i].ProjectWorkType)</td>
.... // more display properties
<td>
@Html.CheckBoxFor(x => x.Projects[i].Selected, new { @class = "big-checkbox" })
@Html.HiddenFor(x => x.Projects[i].ProjectModelId)
</td>
</tr>
}
</tbody>
</table>
}
function submitFormRemoveProjects() {
$("#FlagFormEditProjects").attr({
"value": "RemoveProjects"
});
$('#formEditProjects').submit();
}
返回“确认”视图的操作方法(工作正常)
[HttpGet]
[Authorize(Roles = "Sys Admin, Account Admin, User")]
public async Task<ActionResult> EditProjectsTable([Bind(Include = "Projects,FlagFormEditProjects,FlagformNewProjectStatus")]ProjectIndexViewModel projectIndexViewModel)
{
// Repopulate the Projects collection of ProjectIndexViewModel to
// include only those that have been selected
return View(projectIndexViewModel);
}
从上面的 Action 方法返回的视图(工作正常)请注意,被调用的 Action 方法是使用 Html.BeginForm 调用中的 actionName 变量动态设置的。
@using (Html.BeginForm(actionName, "Project", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.FlagFormNewProjectStatus)
....
<table>
<thead>
....
</thead>
<tbody>
@for (int i = 0; i < Model.Projects.Count; i++)
{
<tr>
<td>@Html.HiddenFor(x => x.Projects[i].ProjectModelId)</td>
<td>@Html.DisplayFor(x => x.Projects[i].ProjectNumber)</td>
<td>@Html.DisplayFor(x => x.Projects[i].ProjectWorkType)</td>
.... // more display properties
</tr>
}
</tbody>
</table>
<input type="submit" value="Delete Permanently" />
}
从该视图调用的控制器操作方法之一的示例,它与视图中的项目不同。不知何故,它与最初选择的项目数量相同,但如果只选择一个,则它具有模型 ID 最低的项目。我不确定如何描述正在发生的事情。但总而言之,正确的 ViewModel 并没有进入下面显示的 POST 方法示例。
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Sys Admin, Account Admin")]
public async Task<ActionResult> DeleteConfirmedMultipleProjects([Bind(Include = "Projects")] ProjectIndexViewModel projectIndexViewModel)
{
if (ModelState.IsValid)
{
// Remove Projects from db and save changes
return RedirectToAction("../Project/Index");
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
请帮忙!
【问题讨论】:
-
代码墙!你能只发布Minimum Viable Code吗?
-
对此感到抱歉....我清理了一下。
-
“我获得了 ViewModel,但与填充 View 的属性不同”是什么意思。您在“DeleteConfirmedMultipleProjects”方法中的预期数据是什么?
-
从 Action 方法
EditProjectsTable构建并传递给 View 的 ViewModel 在从该方法返回的 View 中按预期工作。但是,当这个View中的表单提交给DeleteConfirmedMultipleProjects方法时,同样的Projects不在模型中。但最令人困惑的部分是,正如我在上面试图解释的那样,在初始视图中选择的相同数量的Projects被发送到DeleteConfirmedMultipleProjects,但是例如,如果Projects中只有一个是最初选择,然后发布到... -
...
DeleteConfirmedMultipleProjects,那么它是具有不同模型 ID 的Project。
标签: asp.net-mvc