【问题标题】:Populate a viewmodel with a newly added database ID使用新添加的数据库 ID 填充视图模型
【发布时间】:2012-07-20 09:20:43
【问题描述】:

这是对昨天提出的问题的跟进。

我有一个视图模型,它显示了目标列表。使用 jquery,我可以在屏幕上添加一个新的目标行(对于列出的任何新目标,ID 都设置为 0)。当我单击“保存”按钮将目标列表发布回控制器时,控制器会遍历目标列表,并根据数据库检查 ID。如果未找到 ID,它会创建一个新目标,将其添加到数据库上下文中,并保存更改。然后它检索 ID,并将视图(模型)返回给视图。

问题是,虽然模型中的ID,已经更新为数据库ID——当模型再次在View中渲染时,它的ID还是0。所以如果我再次点击保存,它再次,重新添加将“先前添加的新目标”再次添加到数据库中。

我的控制器如下图:

    //
    // POST: /Objective/Edit/model
    [HttpPost]
    public ActionResult Edit(ObjectivesEdit model)
    {
        if (model.Objectives != null)
        {
             foreach (var item in model.Objectives)
            {
                // find the database row
                Objective objective = db.objectives.Find(item.ID);
                if (objective != null) // if database row is found...
                {
                    objective.objective = item.objective;
                    objective.score = item.score;
                    objective.possscore = item.possscore;
                    objective.comments = item.comments;
                    db.SaveChanges();
                }
                else // database row not found, so create a new objective
                {
                    Objective obj = new Objective();
                    obj.comments=item.comments;
                    obj.objective = item.objective;
                    obj.possscore = item.possscore;
                    obj.score = item.score;
                    db.objectives.Add(obj);
                    db.SaveChanges();
                    // now get the newly created ID 
                    item.ID = obj.ID;
                 }
             }
        }
        return View(model);
    }

我的 ID 正在控制器中设置:

编辑:这里的另一个例子,显示 model.Objectives1.ID 正在更新:

但是当视图渲染它时,它会恢复为 0:

目标列表确定如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcObjectives2.Models
    {
    public class ObjectivesEdit
    {
        public IEnumerable<Objective> Objectives { set; get; }
        public ObjectivesEdit()
        {
            if (Objectives == null)
                Objectives = new List<Objective>();
        }
    }
    }

视图有:

@model MvcObjectives2.Models.ObjectivesEdit

@using (Html.BeginForm())
{
  @Html.EditorFor(x=>x.Objectives)
  <button type="submit" class="btn btn-primary"><i class="icon-ok icon-white"></i> Save</button>
 }

在我的 EditorTemplate (objective.cshtml) 中:

@model  MvcObjectives2.Models.Objective          

<div class="objec">
<div>
@Html.TextBoxFor(x => x.objective})
</div>
<div>
@Html.TextBoxFor(x => x.score})
</div>
<div>
@Html.TextBoxFor(x => x.possscore})
</div>
<div>
@Html.TextBoxFor(x => x.comments})

@Html.HiddenFor(x => x.ID)  // This is the ID where it should now show the new ID from the database, but shows 0

</div>
</div>

我怀疑问题出在我的控制器的某个地方 - 但如果我能就如何让我的视图呈现添加的目标的新 ID 提供任何建议,我将不胜感激。

【问题讨论】:

  • 很可能您新创建的对象还没有 ID,它是在数据库中创建的,并且信息可能没有推送到该对象。
  • 出于好奇,如果您不使用编辑器模板并实际循环渲染标记会怎样?
  • 嗨@SteenT - 这就是将更改保存到数据库,然后检索ID:db.SaveChanges(); // 现在获取新创建的 ID item.ID = obj.ID;
  • 你调试过这个吗?并确保 ID 属性已被填充?
  • 当您将 item.ID 设置为新 ID 时,是否反映在该项目的 Model.Objectives[n].ID 中?

标签: asp.net asp.net-mvc asp.net-mvc-3 entity-framework


【解决方案1】:

改写我的搜索后,我遇到了几篇说这是设计使然的帖子。如果再次显示相同的页面,则 Posted 表单希望显示它发送给控制器的内容。

但是,您可以添加它,这将刷新 ModelState,并明显地显示来自模型的更新值,在控制器中更新:

        ModelState.Clear();
        return View(model);

我不确定这是否还有其他效果 - 但目前看来,它可以正常工作。

谢谢,马克

【讨论】:

    【解决方案2】:

    Html.HiddenFor 在类似的场景中曾经咬过我。问题是当使用这个 Html 助手时,隐藏的值不会在重新发布时更新。

    如果您从表单发布某些内容并在控制器中更改它,当您使用它重新渲染页面时,将使用最初发布到操作的值。

    改为使用

    <input type="hidden" name="ID" id="ID" value="@Html.Encode(Model.ID)" />
    

    【讨论】:

    • 嗨 - 视图将失去将目标呈现为列表的能力,因此字段的名称和 id 属性仅呈现为“ID”而不是(例如)id="Objectives_0__ID" name="Objectives[0].ID" - 所以模型失去了 [ref] - 有没有办法解决这个问题?
    • 在这种情况下,只需确保将隐藏的 Id 和 Name 值排列为与您的模型相同,以便 HTTPPOST 将它们正确绑定到模型。或者,您可以创建自己的 HtmlHelper,它将正确呈现隐藏并使用您所在的对象的名称。
    • 嗨 - 抱歉,我不确定你的意思 - 我将如何正确生成 ID 和名称,以允许视图填充 id="Objectives_0__ID" name="Objectives[0]。 ID" 然后 id="Objectives_1__ID" name="Objectives[1].ID" 在视图中?
    • 即使我渲染为文本框,值仍然是 0。
    • 似乎控制器中的任何属性都发生了变化,例如:obj.cmets="this has been updated in the contoller";仍然会渲染发布到它的任何内容。不只是出于某种原因隐藏的字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多