我想使用相同的视图来编辑博客文章和添加博客文章。但是,我的ID有问题。添加博客帖子时,不需要发布ID值。当模型绑定将表单值绑定到控制器中的BlogPost
对象时,它将在实体框架实体中自动生成ID。
当我编辑博客帖子时,我do需要一个隐藏的表单字段来存储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不能为null。
我接受了OJ关于这个问题的答案,但是我发现了一些让我感到愚蠢的东西,我想分享一下,以防万一有人遇到类似问题。添加/编辑博客的页面甚至根本不需要ID的隐藏字段。原因是因为当我添加博客时,我对该相对URL BlogProject/Admin/AddBlogPost
此URL不包含ID,并且action方法仅呈现页面。添加博客帖子时,该页面将POST到相同的URL。传入的BlogPost
实体由模型绑定填充,并且具有一个空ID,该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对应方法。
让我知道您是否找到更好的方法来完成这项工作。我唯一不满意的部分是接受一个不必要的变量以使方法签名有所不同。
将Id
属性设置为Nullable
,然后检查HasValue
。
mode
中添加某种ViewData
指示器,并根据值显示“隐藏”字段。具有单独的操作和视图以进行编辑和添加