我有以下[HttpGet] Create()方法:
public ActionResult Create(int? parentId)
{
var model = new CreatePersonViewModel();
// pull parent from db
var parent = _db.Persons.FirstOrDefault(s => s.Id == parentId);
model.Parent = parentSet;
return View("Create", model);
}
如果我正在从另一个人的详细信息页面创建一个新人员,我会传入该父人员的ID,然后构建一个包含父项的viewModel。
POST看起来像这样:
[HttpPost]
public ActionResult Create(CreatePersonViewModel viewModel)
{
if (ModelState.IsValid)
{
var parent = viewModel.Parent; // This is always null for some reason
var person = new Person() { Name = viewModel.Name };
// if it has a parent, build new relationship
if (parent != null)
{
person.Parent = parent;
parent.Children.Add(person);
};
_db.Save();
return RedirectToAction("detail", "person", new { personId = person.Id });
}
return View(viewModel);
}
由于某种原因,viewModel被推回到POST方法永远不会包含在GET控制器方法中定义的Parent。我如何告诉MVC将父级从GET推送到POST,而不会使用隐藏字段混淆视图?
如果有帮助,我的观点就在这里:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>CreatePersonViewModel</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
答案 0 :(得分:2)
控制器操作只会接收HTML表单中明确包含的数据。
如果您想接收Parent对象,则需要将其隐藏在隐藏的<input>
标记中。
请注意,来自客户端的任何数据都完全由您的攻击者控制,并且无法信任。
答案 1 :(得分:0)
网络是无状态的,那么服务器如何知道您希望在幕后传递哪些数据?
您可以使用TempData传递数据,它将保留在服务器上,直到您的下一个请求读取它为止。但是我不认为你需要这个。由于您没有使用除父ID和名称之外的任何内容,因此将其存储在客户端上 - 即您的viewmodel仅包含那些字段 - viewmodel中没有实体。
当您发布到服务器加载您的父级时,请分配一个新子级并保存它。将整个对象发送给客户端是没有意义的。
此外,我还会在服务器上验证当前用户是否可以访问这些记录 - 如果适用,除非您的应用程序允许所有用户访问所有人员。