MVC5 ModelView 在编辑操作的 post 上无效
MVC5 ModelView is not valid on post of edit action
我有一个带有 Entity 6 框架的 MVC5 项目,我无法将正确的信息传递给 post 上的编辑操作,以便将其绑定到模型。我的 viewModel 的 ModelState 返回为无效。我不确定我错过了什么。我猜这与我的编辑器模板的设置方式和我的模型结构有关,但我需要一些帮助来解决这个问题。我花了很多时间来改变一些东西来尝试让它工作,但我仍然无法纠正它。
我的视图模型:
namespace CommunityHealth.Models.ViewModels
{
public class ActivityViewModel
{
public virtual IList<JunctionTypeAction> junctionTypeActions{ get; set; }
public virtual IList<JunctionDepartmentAction> junctionDepartmentActions{ get; set; }
public virtual IList<JunctionPopulationAction> junctionPopulationActions { get; set; }
public virtual CommunityAction Action { get; set; }
}
}
社区行动模型:
public partial class CommunityAction
{
public CommunityAction()
{
this.JunctionPopulationActions = new HashSet<JunctionPopulationAction>();
this.JunctionDepartmentActions = new HashSet<JunctionDepartmentAction>();
this.JunctionTypeActions = new HashSet<JunctionTypeAction>();
}
public int ActionID { get; set; }
public System.DateTime StartDate { get; set; }
public Nullable<System.DateTime> EndDate { get; set; }
public string BreifDescription { get; set; }
public Nullable<int> Duration { get; set; }
public int LocationID { get; set; }
public string SubLocation { get; set; }
public int ProgramID { get; set; }
public string Notes { get; set; }
public string AddedBy { get; set; }
public byte[] RecordVersion { get; set; }
public virtual Location Location { get; set; }
public virtual Program Program { get; set; }
public virtual ICollection<JunctionPopulationAction> JunctionPopulationActions { get; set; }
public virtual ICollection<JunctionDepartmentAction> JunctionDepartmentActions { get; set; }
public virtual ICollection<JunctionTypeAction> JunctionTypeActions { get; set; }
}
连接表的模型:
JunctionDepartmentAction:
public partial class JunctionDepartmentAction
{
public int IndexID { get; set; }
public int DepartmentID { get; set; }
public int ActionID { get; set; }
public string SubDepartment { get; set; }
public int Individuals { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
public virtual Department Department { get; set; }
}
JunctionPopulationAction:
public partial class JunctionPopulationAction
{
public int IndexID { get; set; }
public int PopulationID { get; set; }
public int ActionID { get; set; }
public bool isActive { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
public virtual TargetPopulation TargetPopulation { get; set; }
}
JunctionTypeAction:
public partial class JunctionTypeAction
{
public int IndexID { get; set; }
public int TypeID { get; set; }
public int ActionID { get; set; }
public virtual ActivityType ActivityType { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
}
事件控制器编辑操作方法:
// GET: /Event/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CommunityAction communityaction = await db.CommunityActions.FindAsync(id);
ActivityViewModel activityviewmodel = new ActivityViewModel();
activityviewmodel.Action = communityaction;
IList<JunctionTypeAction> junctiontypeactions = await db.JunctionTypeActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
IList<JunctionDepartmentAction> junctiondepartmentactions = await db.JunctionDepartmentActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
IList<JunctionPopulationAction> junctionpopulationactions = await db.JunctionPopulationActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
activityviewmodel.junctionTypeActions = junctiontypeactions.ToList();
activityviewmodel.junctionDepartmentActions = junctiondepartmentactions.ToList();
activityviewmodel.junctionPopulationActions = junctionpopulationactions.ToList();
if (communityaction == null)
{
return HttpNotFound();
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activityviewmodel.Action.LocationID);
ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activityviewmodel.Action.ProgramID);
return View(activityviewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ActivityViewModel activity)
{
//request added for debugging purposes
Request.ToString();
if (ModelState.IsValid)
{
db.Entry(activity).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activity.Action.LocationID);
ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activity.Action.ProgramID);
return View(activity);
}
最后是我的观点。我为数据库中的联结表使用了三个编辑器模板,为 CommunityAction 对象使用了另一个。然后我有一个事件视图,它使用三个编辑器模板来显示 ViewModel 的各个部分。
CommunityAction.cshtml:
@model CommunityHealth.Models.CommunityAction
<div class="form-horizontal">
<h4>CommunityAction</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.RecordVersion)
<div class="form-group">
@Html.LabelFor(model => model.StartDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.StartDate)
@Html.ValidationMessageFor(model => model.StartDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EndDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EndDate)
@Html.ValidationMessageFor(model => model.EndDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.BreifDescription, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.BreifDescription)
@Html.ValidationMessageFor(model => model.BreifDescription)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Duration, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Duration)
@Html.ValidationMessageFor(model => model.Duration)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LocationID, "Location", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Location, ViewBag.LocationID as SelectList, new { htmlAttributes = new { @class = "control-form" } })
@Html.ValidationMessageFor(model => model.Location)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SubLocation, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SubLocation)
@Html.ValidationMessageFor(model => model.SubLocation)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ProgramID, "Program", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.ProgramID, ViewBag.ProgramID as SelectList, new { htmlAttributes = new { @class = "control-form" } })
@Html.ValidationMessageFor(model => model.Program)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Notes, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Notes)
@Html.ValidationMessageFor(model => model.Notes)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.AddedBy, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.AddedBy)
@Html.ValidationMessageFor(model => model.AddedBy)
</div>
</div>
<div class="form-group">
<div class="col-md-10">
</div>
</div>
</div>
JunctionTypeAction.cshtml:
@model CommunityHealth.Models.JunctionTypeAction
<div class="type">
<fieldset>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.TypeID, "TypeName", new { @class = "control-label col-md-2" })
</fieldset>
</div>
JunctionDepartmentAction.cshtml:
@model CommunityHealth.Models.JunctionDepartmentAction
@using CommunityHealth.Models
<div>
<table>
<tbody>
<tr>
<td>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.DepartmentID, "DepartmentName", new { @class = "control-label col-md-2" })
</td>
<td>
@Html.EditorFor(model => model.SubDepartment, "SubDepartment", new { @class = "control-label col-md-2 " })
</td>
<td>
@Html.EditorFor(model => model.Individuals)
</td>
</tr>
</tbody>
</table>
</div>
JunctionPopulationAction.cshtml:
@model CommunityHealth.Models.JunctionPopulationAction
<div class="population">
<fieldset>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.PopulationID, "PopulationName", new { @class = "control-label col-md-2" })
</fieldset>
</div>
Views\Event\Edit.cshtml:
@model CommunityHealth.Models.ViewModels.ActivityViewModel
@using CommunityHealth.Models.ViewModels;
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm("Edit","Event",FormMethod.Post))
{
@Html.AntiForgeryToken()
<div>
<div class="form-group">
@Html.EditorFor(model => model.Action)
</div>
<div class="form-group">
@Html.Label("Types")
<div class="col-md-10">
<fieldset>
@for (int x = 0; x < Model.junctionTypeActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionTypeActions[x])
}
</fieldset>
</div>
</div>
<div class="form-group">
@Html.Label("Departments")
<div class="col-md-10">
@for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionDepartmentActions[x])
}
</div>
</div>
<div class="form-group">
@Html.Label("Target Populations")
<div class="col-md-10">
@for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionPopulationActions[x])
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<div>
@Html.ActionLink("Back to List", "Index")
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
我在检查请求时遇到此错误:
"The parameter conversion from type 'System.String' to type 'CommunityHealth.Models.CommunityAction' failed because no type converter can convert between these types."
该错误的原因是因为您的模型有一个名为 activity
(typeof CommunityAction
) 的 属性,并且您的 post 方法的参数也被命名为activity
。将参数名称更改为模型
中 属性 名称以外的任何名称
public async Task<ActionResult> Edit(ActivityViewModel model)
{
....
}
旁注
- 只需使用
@Html.EditorFor(m => m.junctionTypeActions)
生成
html 用于集合(不在 for
循环中)。 @Html.EditorFor()
足够聪明,可以识别集合并生成正确的
html.
- 生成所有这些隐藏的输入是不好的做法并且会降级
性能(任何恶意用户都可以更改这些值)。
为每个或您的类型使用仅包含
您需要 display/edit.
的属性
我有一个带有 Entity 6 框架的 MVC5 项目,我无法将正确的信息传递给 post 上的编辑操作,以便将其绑定到模型。我的 viewModel 的 ModelState 返回为无效。我不确定我错过了什么。我猜这与我的编辑器模板的设置方式和我的模型结构有关,但我需要一些帮助来解决这个问题。我花了很多时间来改变一些东西来尝试让它工作,但我仍然无法纠正它。
我的视图模型:
namespace CommunityHealth.Models.ViewModels
{
public class ActivityViewModel
{
public virtual IList<JunctionTypeAction> junctionTypeActions{ get; set; }
public virtual IList<JunctionDepartmentAction> junctionDepartmentActions{ get; set; }
public virtual IList<JunctionPopulationAction> junctionPopulationActions { get; set; }
public virtual CommunityAction Action { get; set; }
}
}
社区行动模型:
public partial class CommunityAction
{
public CommunityAction()
{
this.JunctionPopulationActions = new HashSet<JunctionPopulationAction>();
this.JunctionDepartmentActions = new HashSet<JunctionDepartmentAction>();
this.JunctionTypeActions = new HashSet<JunctionTypeAction>();
}
public int ActionID { get; set; }
public System.DateTime StartDate { get; set; }
public Nullable<System.DateTime> EndDate { get; set; }
public string BreifDescription { get; set; }
public Nullable<int> Duration { get; set; }
public int LocationID { get; set; }
public string SubLocation { get; set; }
public int ProgramID { get; set; }
public string Notes { get; set; }
public string AddedBy { get; set; }
public byte[] RecordVersion { get; set; }
public virtual Location Location { get; set; }
public virtual Program Program { get; set; }
public virtual ICollection<JunctionPopulationAction> JunctionPopulationActions { get; set; }
public virtual ICollection<JunctionDepartmentAction> JunctionDepartmentActions { get; set; }
public virtual ICollection<JunctionTypeAction> JunctionTypeActions { get; set; }
}
连接表的模型: JunctionDepartmentAction:
public partial class JunctionDepartmentAction
{
public int IndexID { get; set; }
public int DepartmentID { get; set; }
public int ActionID { get; set; }
public string SubDepartment { get; set; }
public int Individuals { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
public virtual Department Department { get; set; }
}
JunctionPopulationAction:
public partial class JunctionPopulationAction
{
public int IndexID { get; set; }
public int PopulationID { get; set; }
public int ActionID { get; set; }
public bool isActive { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
public virtual TargetPopulation TargetPopulation { get; set; }
}
JunctionTypeAction:
public partial class JunctionTypeAction
{
public int IndexID { get; set; }
public int TypeID { get; set; }
public int ActionID { get; set; }
public virtual ActivityType ActivityType { get; set; }
public virtual CommunityAction CommunityAction { get; set; }
}
事件控制器编辑操作方法:
// GET: /Event/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CommunityAction communityaction = await db.CommunityActions.FindAsync(id);
ActivityViewModel activityviewmodel = new ActivityViewModel();
activityviewmodel.Action = communityaction;
IList<JunctionTypeAction> junctiontypeactions = await db.JunctionTypeActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
IList<JunctionDepartmentAction> junctiondepartmentactions = await db.JunctionDepartmentActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
IList<JunctionPopulationAction> junctionpopulationactions = await db.JunctionPopulationActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync();
activityviewmodel.junctionTypeActions = junctiontypeactions.ToList();
activityviewmodel.junctionDepartmentActions = junctiondepartmentactions.ToList();
activityviewmodel.junctionPopulationActions = junctionpopulationactions.ToList();
if (communityaction == null)
{
return HttpNotFound();
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activityviewmodel.Action.LocationID);
ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activityviewmodel.Action.ProgramID);
return View(activityviewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(ActivityViewModel activity)
{
//request added for debugging purposes
Request.ToString();
if (ModelState.IsValid)
{
db.Entry(activity).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activity.Action.LocationID);
ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activity.Action.ProgramID);
return View(activity);
}
最后是我的观点。我为数据库中的联结表使用了三个编辑器模板,为 CommunityAction 对象使用了另一个。然后我有一个事件视图,它使用三个编辑器模板来显示 ViewModel 的各个部分。
CommunityAction.cshtml:
@model CommunityHealth.Models.CommunityAction
<div class="form-horizontal">
<h4>CommunityAction</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.RecordVersion)
<div class="form-group">
@Html.LabelFor(model => model.StartDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.StartDate)
@Html.ValidationMessageFor(model => model.StartDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EndDate, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EndDate)
@Html.ValidationMessageFor(model => model.EndDate)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.BreifDescription, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.BreifDescription)
@Html.ValidationMessageFor(model => model.BreifDescription)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Duration, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Duration)
@Html.ValidationMessageFor(model => model.Duration)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LocationID, "Location", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Location, ViewBag.LocationID as SelectList, new { htmlAttributes = new { @class = "control-form" } })
@Html.ValidationMessageFor(model => model.Location)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.SubLocation, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SubLocation)
@Html.ValidationMessageFor(model => model.SubLocation)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ProgramID, "Program", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.ProgramID, ViewBag.ProgramID as SelectList, new { htmlAttributes = new { @class = "control-form" } })
@Html.ValidationMessageFor(model => model.Program)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Notes, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Notes)
@Html.ValidationMessageFor(model => model.Notes)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.AddedBy, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.AddedBy)
@Html.ValidationMessageFor(model => model.AddedBy)
</div>
</div>
<div class="form-group">
<div class="col-md-10">
</div>
</div>
</div>
JunctionTypeAction.cshtml:
@model CommunityHealth.Models.JunctionTypeAction
<div class="type">
<fieldset>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.TypeID, "TypeName", new { @class = "control-label col-md-2" })
</fieldset>
</div>
JunctionDepartmentAction.cshtml:
@model CommunityHealth.Models.JunctionDepartmentAction
@using CommunityHealth.Models
<div>
<table>
<tbody>
<tr>
<td>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.DepartmentID, "DepartmentName", new { @class = "control-label col-md-2" })
</td>
<td>
@Html.EditorFor(model => model.SubDepartment, "SubDepartment", new { @class = "control-label col-md-2 " })
</td>
<td>
@Html.EditorFor(model => model.Individuals)
</td>
</tr>
</tbody>
</table>
</div>
JunctionPopulationAction.cshtml:
@model CommunityHealth.Models.JunctionPopulationAction
<div class="population">
<fieldset>
@Html.HiddenFor(model => model.ActionID)
@Html.HiddenFor(model => model.IndexID)
@Html.EditorFor(model => model.PopulationID, "PopulationName", new { @class = "control-label col-md-2" })
</fieldset>
</div>
Views\Event\Edit.cshtml:
@model CommunityHealth.Models.ViewModels.ActivityViewModel
@using CommunityHealth.Models.ViewModels;
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm("Edit","Event",FormMethod.Post))
{
@Html.AntiForgeryToken()
<div>
<div class="form-group">
@Html.EditorFor(model => model.Action)
</div>
<div class="form-group">
@Html.Label("Types")
<div class="col-md-10">
<fieldset>
@for (int x = 0; x < Model.junctionTypeActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionTypeActions[x])
}
</fieldset>
</div>
</div>
<div class="form-group">
@Html.Label("Departments")
<div class="col-md-10">
@for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionDepartmentActions[x])
}
</div>
</div>
<div class="form-group">
@Html.Label("Target Populations")
<div class="col-md-10">
@for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++)
{
@Html.EditorFor(model => model.junctionPopulationActions[x])
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<div>
@Html.ActionLink("Back to List", "Index")
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
我在检查请求时遇到此错误:
"The parameter conversion from type 'System.String' to type 'CommunityHealth.Models.CommunityAction' failed because no type converter can convert between these types."
该错误的原因是因为您的模型有一个名为 activity
(typeof CommunityAction
) 的 属性,并且您的 post 方法的参数也被命名为activity
。将参数名称更改为模型
public async Task<ActionResult> Edit(ActivityViewModel model)
{
....
}
旁注
- 只需使用
@Html.EditorFor(m => m.junctionTypeActions)
生成 html 用于集合(不在for
循环中)。@Html.EditorFor()
足够聪明,可以识别集合并生成正确的 html. - 生成所有这些隐藏的输入是不好的做法并且会降级 性能(任何恶意用户都可以更改这些值)。 为每个或您的类型使用仅包含 您需要 display/edit. 的属性