简体   繁体   English

使用ASP.Net MVC中的模型绑定器更新父/子记录

[英]Updating Parent/Child Records with model binders in ASP.Net MVC

I have modified the Nerd Dinner application to allow editing of child records by adding the following code to the DinnerForm.ascx 我修改了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>

it is rendering this: 它呈现这个:

<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>   

I have not modified the DinnersControler's Post Edit Action method. 我没有修改DinnersControler的Post Edit Action方法。 The Parent dinner is getting updated as usual, but it appears the UpdateModel(dinner); 父母的晚餐照常更新,但它似乎是UpdateModel(晚餐); is not seeing/updating the child RSVP records. 没有看到/更新子RSVP记录。

I have tried a few variations on rendering the child records so that the Model binders will see the collection, with no luck. 我已经尝试了一些渲染子记录的变体,以便模型绑定器可以看到集合,没有运气。

Is updating parent/child records in one shot by calling UpdateModel(Parent); 通过调用UpdateModel(Parent)一次更新父/子记录; possible with the current model binders? 可能与当前的模型粘合剂?

I haven't been able to do this myself. 我自己无法做到这一点。

I know that you can update a single child element, ie, Dinner.RSV automatically. 我知道您可以自动更新单个子元素,即Dinner.RSV。 I've never seen the ability to update a child enumerable, which would require the binding to know which property is the ID and look for it (ie, Dinner.RSVP.Where(r => r.RSVP_ID == input_id) and then update that). 我从未见过更新子枚举的能力,这需要绑定才能知道哪个属性是ID并查找它(即Dinner.RSVP.Where(r => r.RSVP_ID == input_id)然后更新那个)。 I don't know enough about custom binding to do something like that. 我不太了解自定义绑定做类似的事情。

However, what I have done is to do a loop and specify the rsvp and the int as a prefix: 但是,我所做的是做一个循环并指定rsvp和int作为前缀:

So you do: 所以你也是:

UpdateModel("Dinner", Dinner);

to update the parent and then: 更新父级然后:

int i = 0;

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

Not quite as clean, but it works well for me. 不太干净,但对我来说效果很好。 It might take a bit more effort to build in validation, though (you want to validate all at the same time, and make sure you don't jump back to the view on the first RSVP with an error). 但是,构建验证可能需要更多的努力(您希望同时验证所有内容,并确保不会在第一个RSVP上跳回到视图并出现错误)。

EDIT : Fixed the code to reflect the OP's solution, including a bug in my parameter order. 编辑 :修复了代码以反映OP的解决方案,包括我的参数顺序中的错误。 With that being said, I'm more comfortable using the RSVP.ID property than a running integer. 话虽如此,我使用RSVP.ID属性比运行整数更舒服。 As long as you know that Dinner.RSVPs will be the same on the POST as the GET (I'm confident of this in my code), then using the RSVP.ID will work. 只要您知道Dinner.RSVP在POST上与GET相同(我在我的代码中对此有信心),那么使用RSVP.ID将起作用。 Should RSVPs be different, then only those present on both will get updated. 如果RSVP与RSVP不同,那么只有那两个存在的RSVP才会更新。 However, using the sequential int could potentially cause the wrong object to be updated. 但是,使用sequential int可能会导致更新错误的对象。

Hope that helps, James 希望有所帮助,詹姆斯

Ok, so nobody's answering. 好的,所以没有人回答。 I don't know the nerddinner app but was interested by your problem. 我不知道nerddinner应用程序,但对您的问题感兴趣。 Was hoping to see some answers but, well, none yet. 希望看到一些答案,但是,还没有。 Not 100% sure because of lack of familiarity with ndinner, but could it be related to this post where they mention binding/updating only when a property is explicitly passed? 不是100%肯定,因为对ndinner不熟悉,但它是否与这篇文章有关 ,他们只在明确传递属性时才提到绑定/更新?

Your question is whether updating parent/child records in one shot by calling UpdateModel(Parent); 您的问题是通过调用UpdateModel(Parent)来一次更新父/子记录; possible with the current model binders? 可能与当前的模型粘合剂?

Yes, this is possible. 是的,这是可能的。 However, it is not possible (without some minor workarounds) if you are using Linq-to-Sql and your child objects are exposed via EntitySet<T> instead of something like IList<T> . 然而,这是不可能的(不包括一些小的解决方法)如果你正在使用LINQ到SQL和你的孩子对象通过暴露EntitySet<T>而不是像IList<T> I believe this will be (has been?) addressed in the next version of MVC due out with ASP.NET 4.0. 我相信这将是(已经?)在ASP.NET 4.0的下一版MVC中解决的问题。 For the time being, though, the MVC default model binder does not seem to understand how to work with EntitySet. 但就目前而言,MVC默认模型绑定器似乎并不了解如何使用EntitySet。

Please see this other answer I wrote on a related question some time ago, with details about how I am now dealing with (working around) this situation in certain simple cases. 请看一下我之前在相关问题上写的这个其他答案 ,详细介绍了我在某些简单情况下如何处理(解决)这种情况。 In doing this, I've had to stop worrying so much about how "ideal" this solution is from a DDD/OOP perspective, as a trade-off to simply getting MVC and LTS to play together nicely with minimal effort. 在这样做的过程中,我不得不停止担心这个解决方案从DDD / OOP的角度来看是多么“理想”,作为简单地让MVC和LTS以最小的努力很好地协同工作的权衡。

Note, I will admit that James S's solution is probably more "pure," but in order to do this in "one shot" as you ask, you'll need to either wait for ASP.NET 4.0, or use a workaround similar to what you'll find in my other post. 请注意,我承认James S的解决方案可能更“纯粹”,但是为了按照您的要求“一次性”执行此操作,您需要等待ASP.NET 4.0,或者使用类似于你会在我的其他帖子中找到什么。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM