【问题标题】:Updating Parent/Child Records with model binders in ASP.Net MVC在 ASP.Net MVC 中使用模型绑定更新父/子记录
【发布时间】:2010-11-09 08:50:30
【问题描述】:

我已经修改了Nerd Dinner 应用程序以允许通过将以下代码添加到 DinnerForm.ascx 来编辑子记录

  <p>
    <%int i = 0;
   foreach (NerdDinner.Models.RSVP rsvp in this.Model.Dinner.RSVPs)
       { %>

        <%= Html.Hidden("Dinner.RSVPs[" + i + "].RsvpID", rsvp.RsvpID)%>
        <%= Html.Hidden("Dinner.RSVPs[" + i + "].DinnerID", rsvp.DinnerID)%>
        <%= Html.TextBox("Dinner.RSVPs[" + i + "].AttendeeName", rsvp.AttendeeName)%>
    <% i += 1;
   } %>
    </p>

它正在渲染这个:

<p>
    <input id="Dinner_RSVPs[0]_RsvpID" name="Dinner.RSVPs[0].RsvpID" type="hidden" value="36" />
        <input id="Dinner_RSVPs[0]_DinnerID" name="Dinner.RSVPs[0].DinnerID" type="hidden" value="63" />
        <input id="Dinner_RSVPs[0]_AttendeeName" name="Dinner.RSVPs[0].AttendeeName" type="text" value="kp" />
    <input id="Dinner_RSVPs[1]_RsvpID" name="Dinner.RSVPs[1].RsvpID" type="hidden" value="37" />
        <input id="Dinner_RSVPs[1]_DinnerID" name="Dinner.RSVPs[1].DinnerID" type="hidden" value="63" />
        <input id="Dinner_RSVPs[1]_AttendeeName" name="Dinner.RSVPs[1].AttendeeName" type="text" value="jim" />

    </p>   

我没有修改 DinnersControler 的 Post Edit Action 方法。家长晚餐照常更新,但显示为 UpdateModel(dinner);未查看/更新子 RSVP 记录。

我尝试了几种渲染子记录的变体,以便模型绑定器可以看到集合,但没有运气。

正在通过调用 UpdateModel(Parent) 一次性更新父/子记录;可以使用当前的模型绑定器吗?

【问题讨论】:

    标签: asp.net-mvc modelbinders master-detail


    【解决方案1】:

    您的问题是是否通过调用 UpdateModel(Parent); 一次性更新父/子记录;可以使用当前的模型绑定器吗?

    是的,这是可能的。但是,如果您使用 Linq-to-Sql 并且您的子对象通过EntitySet&lt;T&gt; 而不是IList&lt;T&gt; 之类的方式公开,则不可能(没有一些小的解决方法)。我相信这将(已经?)在 ASP.NET 4.0 的下一个 MVC 版本中得到解决。不过,目前 MVC 默认模型绑定器似乎不了解如何使用 EntitySet。

    请看other answer我前段时间在一个相关问题上写的,详细说明了我现在在某些简单情况下如何处理(解决)这种情况。在这样做的过程中,我不得不不再担心从 DDD/OOP 的角度来看这个解决方案有多“理想”,作为一种折衷方案,只是让 MVC 和 LTS 以最小的努力很好地协同工作。

    注意,我承认 James S 的解决方案可能更“纯粹”,但为了按照您的要求“一次性”完成此操作,您需要等待 ASP.NET 4.0,或者使用解决方法类似于您将在我的另一篇文章中找到的解决方法。

    祝你好运!

    【讨论】:

      【解决方案2】:

      我自己无法做到这一点。

      我知道您可以自动更新单个子元素,即 Dinner.RSV。我从未见过更新子可枚举的能力,这需要绑定知道哪个属性是 ID 并查找它(即,Dinner.RSVP.Where(r => r.RSVP_ID == input_id) 然后更新)。我对自定义绑定知之甚少,无法执行此类操作。

      但是,我所做的是做一个循环并指定 rsvp 和 int 作为前缀:

      所以你这样做:

      UpdateModel("Dinner", Dinner);
      

      更新父级然后:

      int i = 0;
      
      foreach (var r in Dinner.RSVPs) {
        UpdateModel(r, "Dinner.RSVPs[" + i++ + "]");
      }
      

      不太干净,但对我来说效果很好。不过,构建验证可能需要更多的努力(您想同时验证所有内容,并确保您不会因为错误跳回第一个 RSVP 的视图)。

      编辑:修复了代码以反映 OP 的解决方案,包括我的参数顺序中的错误。话虽如此,我更喜欢使用 RSVP.ID 属性而不是运行整数。只要您知道 Dinner.RSVPs 在 POST 上与 GET 相同(我在我的代码中对此很有信心),那么使用 RSVP.ID 就可以了。如果 RSVP 不同,那么只有同时出现的那些才会更新。但是,使用顺序 int 可能会导致更新错误的对象。

      希望对您有所帮助, 詹姆斯

      【讨论】:

      • @jamesshannon 这个答案很接近。修复循环中的更新模型以读取 int i = 0; foreach (RSVP r in Dinner.RSVPs) { UpdateModel(r, "Dinner.RSVPs[" + i + "]");我++; } 我们可以将其标记为已完成/已回答。
      【解决方案3】:

      好的,所以没有人回答。我不知道 nerddinner 应用程序,但对您的问题很感兴趣。希望看到一些答案,但是,还没有。由于对 ndinner 不熟悉,不能 100% 确定,但它是否与 this post 相关,他们仅在显式传递属性时才提到绑定/更新?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多