【问题标题】:ASP.net MVC 2.0 using the same form for adding and editingASP.net MVC 2.0 使用相同的表格进行添加和编辑
【发布时间】: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


    【解决方案1】:

    几个选项:

    • 将您的Id 属性设为Nullable 并检查HasValue
    • 将某种mode 指示器添加到您的ViewData 并根据值显示隐藏字段。
    • 将表单主体放在局部视图中,并将其包含在两个不同的视图中,一个有隐藏字段,一个没有隐藏字段。

    【讨论】:

    • 我做了模式指示器,这似乎有效。我确实喜欢将编辑器放在局部视图中,然后执行两个不同的视图以进行添加和编辑的想法。
    • 最后一个选项也是我的偏好。但有时简单的赢家:)
    【解决方案2】:

    我在项目中所做的如下:

    • 拥有单独的操作和视图以进行编辑和添加
    • 在编辑 URL 中而不是在隐藏字段中传递对象的 ID
    • 为对象使用共享编辑器模板,以避免重复编写相同的样板代码

    如果您正确执行此操作,添加和编辑视图将非常小。

    【讨论】:

    • 为什么要使用单独的控制器进行编辑和添加?这些似乎应该是 same 控制器的单独操作。
    • 糟糕!那是一个错字。我的意思是分开的行动。我有两个动作而不是一个动作,因为在使用 LINQ to Entities 时编辑和添加需要一些不同的代码。在添加动作中,我可以直接在方法的参数中将模型绑定到对象。在编辑动作中,我需要先拉起实体,然后使用UpdateModel方法。
    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2018-05-29
    • 2011-01-19
    • 2014-05-15
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多