【发布时间】:2011-02-16 23:33:28
【问题描述】:
我想使用相同的视图来编辑博客文章和添加博客文章。但是,我的 ID 有问题。添加博客文章时,我不需要发布 ID 值。当模型绑定将表单值绑定到控制器中的BlogPost对象时,它会在实体框架实体中自动生成ID。
当我编辑博客文章时,我确实需要一个隐藏的表单字段来存储 ID,以便它伴随下一个表单文章。这是我现在的看法。
<% using (Html.BeginForm("CommitEditBlogPost", "Admin"))
{ %>
<% if (Model != null)
{ %>
<%: Html.HiddenFor(x => x.Id)%>
<% } %>
Title:<br />
<%: Html.TextBoxFor(x => x.Title, new { Style = "Width: 90%;" })%>
<br />
<br />
Summary:<br />
<%: Html.TextAreaFor(x => x.Summary, new { Style = "Width: 90%; Height: 50px;" }) %>
<br />
<br />
Body:<br />
<%: Html.TextAreaFor(x => x.Body, new { Style = "Height: 250px; Width: 90%;" })%>
<br />
<br />
<input type="submit" value="Submit" />
<% } %>
现在检查模型是否为 NULL 是了解我是在编辑博客文章还是添加一篇文章的好方法,因为当我添加一篇博文时,它将为 null,因为它尚未创建.当出现错误并且实体无效时,问题就出现了。当控制器在无效模型之后呈现表单时,Model != null 评估为 false,即使我们正在编辑帖子并且显然存在模型。如果我在添加帖子时呈现 ID 的隐藏输入字段,则会收到一条错误消息,指出 ID 不能为空。
编辑
我选择了 OJ 对这个问题的回答,但是我发现了一些让我觉得很傻的东西,我想分享它以防万一有人遇到类似问题。添加/编辑博客的页面甚至不需要隐藏的 id 字段。原因是当我添加博客时,我对这个相对 URL BlogProject/Admin/AddBlogPost 执行 GET 操作
此 URL 不包含 ID,并且操作方法仅呈现页面。添加博客文章时,该页面会对同一 URL 进行 POST。传入的BlogPost 实体由模型绑定填充,并具有一个空 Id,它将由 EF 在保存更改期间生成。
现在在编辑博客文章时,URL 是 BlogProject/Admin/EditBlogPost/{Id}。此 URL 包含博客文章的 id,并且由于页面回发到完全相同的 URL,因此 id 与 POST 一起发送到执行编辑的操作方法。
我遇到的唯一问题是操作方法不能具有相同的签名。
[HttpGet]
public ViewResult EditBlogPost(int Id)
{
}
[HttpPost]
public ViewResult EditBlogPost(int Id)
{
}
如果你尝试使用上面的这两种方法,编译器会对你大喊大叫。在没有动作或控制器参数的情况下执行Html.BeginForm() 时回发 Id 实在是太方便了。因此,我没有更改 POST 方法的名称,而是修改了参数以包含 FormCollection。
像这样:
[HttpPost]
public ViewResult EditBlogPost(int Id, FormCollection formCollection)
{
// You can then use formCollection as the IValueProvider for UpdateModel()
// and TryUpdateModel() if you wish. I mean, you might as well use the
// argument since you're taking it.
}
formCollection 变量通过模型绑定填充,其内容与默认情况下 Request.Form 的内容相同。您不必将此集合用于UpdateModel() 或TryUpdateModel(),但我这样做只是为了让我不觉得该集合毫无意义,因为它实际上只是为了使方法签名与其对应的 GET 不同。
如果您找到更好的方法来完成这项工作,请告诉我。我唯一不满意的部分是采用不必要的变量来使方法签名不同。
【问题讨论】:
标签: c# asp.net-mvc entity-framework asp.net-mvc-2 entity-framework-4