Asp.net mvc 模型未在POST上正确提交/绑定
场景: 我有一个表,其中包含从ViewModel填充的行。每行都有复选框,允许用户选中一行或多行,然后从下拉菜单中的操作中进行选择,以编辑选定行的属性 到目前为止,一切正常,我可以让ViewModel正确通过,然后在后期操作方法中使用它及其所有属性。我可以根据用户选择的选项进行更改 但是,由于下拉列表中的某些选项会做出相当大且不可逆转的更改,因此我使用GET调用一个新视图,并使用选定的行填充一个新表,并要求用户确认他们想要进行更改。到目前为止,一切都还不错。新视图按预期仅填充上一个视图中选定的行 问题: 在用户确认其意图后,将使用POST调用操作方法。正确填充当前视图的ViewModel正在正确地进入控制器。我得到了ViewModel,但与填充视图的属性不同 视图模型Asp.net mvc 模型未在POST上正确提交/绑定,asp.net-mvc,Asp.net Mvc,场景: 我有一个表,其中包含从ViewModel填充的行。每行都有复选框,允许用户选中一行或多行,然后从下拉菜单中的操作中进行选择,以编辑选定行的属性 到目前为止,一切正常,我可以让ViewModel正确通过,然后在后期操作方法中使用它及其所有属性。我可以根据用户选择的选项进行更改 但是,由于下拉列表中的某些选项会做出相当大且不可逆转的更改,因此我使用GET调用一个新视图,并使用选定的行填充一个新表,并要求用户确认他们想要进行更改。到目前为止,一切都还不错。新视图按预期仅填充上一个视图中选定的行
public class ProjectIndexViewModel
{
public List<ProjectDetailsViewModel> Projects { get; set; }
public string FlagFormEditProjects { get; set; }
public string FlagFormNewProjectStatus { get; set; }
}
公共类项目索引模型
{
公共列表项目{get;set;}
公共字符串FlagFormEditProjects{get;set;}
公共字符串FlagFormNewProjectStatus{get;set;}
}
列表项目
用于填充表中的行,而项目在控制器中的后期操作方法中没有正确绑定
选中复选框的初始视图。请注意选择下拉选项时调用的其中一个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();
}
@使用(Html.BeginForm(“EditProjectsTable”,“Project”,FormMethod.Get,new{name=“formEditProjects”,id=“formEditProjects”}))
{
@Html.HiddenFor(item=>item.FlagFormEditProjects)
@Html.HiddenFor(item=>item.FlagFormNewProjectStatus)
....
....
@对于(int i=0;ix.Projects[i].ProjectNumber)
@DisplayFor(x=>x.Projects[i].ProjectWorkType)
..//更多显示属性
@Html.CheckBoxFor(x=>x.Projects[i]。选中,新建{@class=“big checkbox”})
@Html.HiddenFor(x=>x.Projects[i].ProjectModelId)
}
}
函数submitFormRemoveProjects(){
$(“#FlagFormEditProjects”).attr({
“值”:“移除项目”
});
$('#formEditProjects')。提交();
}
返回“确认”视图的操作方法(工作正常)
[HttpGet]
[授权(角色=“系统管理员、帐户管理员、用户”)]
公共异步任务EditProjectsTable([Bind(Include=“Projects,FlagFormEditProjects,FlagformNewProjectStatus”)]ProjectIndexViewModel ProjectIndexViewModel)
{
//将ProjectIndexViewModel的项目集合重新填充到
//仅包括已选定的项目
返回视图(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" />
}
@使用(Html.BeginForm(actionName,“Project”,FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model=>model.FlagFormNewProjectStatus)
....
....
@对于(int i=0;ix.Projects[i].ProjectModelId)
@DisplayFor(x=>x.Projects[i].ProjectNumber)
@DisplayFor(x=>x.Projects[i].ProjectWorkType)
..//更多显示属性
}
}
从该视图调用的控制器操作方法之一的示例,该方法与视图中的项目不同。不知何故,它的项目数与最初选择的项目数相同,但如果只选择了一个,它的项目模型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);
}
[HttpPost]
[ValidateAntiForgeryToken]
[授权(Roles=“Sys Admin,Account Admin”)]
公共异步任务DeleteConfirmedMultipleProject([Bind(Include=“Projects”)]ProjectIndexViewModel ProjectIndexViewModel)
{
if(ModelState.IsValid)
{
//从数据库中删除项目并保存更改
返回重定向到操作(“../Project/Index”);
}
返回新的HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
请帮忙 我认为你的问题来自这一部分:
@Html.CheckBoxFor(x => x.Projects[i].Selected, new { @class = "big-checkbox" })
@Html.HiddenFor(x => x.Projects[i].ProjectModelId)
我以前遇到过这个错误,我所做的是向ProjectDetailsViewModel
添加一个布尔属性,比如IsSelected
。
那么你应该:
@Html.CheckBoxFor(x => x.Projects[i].IsSelected, new { @class = "big-checkbox" })
然后在方法上,您应该添加:
foreach (var project in ProjectIndexViewModel.Projects )
{
if (project.IsSelected==true)
"put your logic here"
}
问题是,当您从第一个视图提交到
EditProjectsTable()
方法时,所有表单控件的值都会添加到ModelState
重新填充ProjectDetailsViewModel
集合不会更新ModelState
,返回视图时,DisplayFor()
方法将显示正确的值,因为DisplayFor()
使用模型的值,但是
@Html.HiddenFor(x => x.Projects[i].ProjectModelId)
将使用Mod中的值
@Html.HiddenFor(x => x.Projects[i].ProjectModelId)
[HttpGet]
[Authorize(Roles = "Sys Admin, Account Admin, User")]
public async Task<ActionResult> EditProjectsTable(ProjectIndexViewModel projectIndexViewModel)
{
// Repopulate the Projects collection of ProjectIndexViewModel to
// include only those that have been selected
ModelState.Clear(); // add this
return View(projectIndexViewModel);
}