结合儿童的可编辑列表 [英] Binding an editable list of children

查看:115
本文介绍了结合儿童的可编辑列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR 的:在我的ASP.NET应用程序MVC3,我应该如何实现一个视图,让我在同一时间作为列表的详细信息编辑父实体的细节的孩子们实体?

TL;DR: In my ASP.NET MVC3 App, how should I implement a View that allows me to edit details of a 'parent' entity at the same time as the details of a list of 'children' entities ?

更新:我接受 @ TORM的回答,因为他提供的< A HREF =HTTP://www.$c$ctuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx相对=nofollow>一个链接,让一些解释为什么我目前的解决方案可能是因为它得到一样好。 然而,我们很乐意听到的话,任何人有任何替代品!

Update: I'm accepting @torm's answer because he provided a link that gives some explanation as to why my current solution may be as good as it gets. However, we'd love to hear if anyone else have any alternative!

我一直在寻找和阅读(见底部的一些调查结果的参考一节至今)。
不过,我还是觉得像有什么东西'臭'有我迄今发现的解决方案。我不知道你们有一个更优雅的答案或建议(或可以解释为什么这可能是尽善尽美)。 在此先感谢!

I've been searching and reading (see the 'References' section at the bottom for some of the findings so far). However, I still feel like there's something 'smelly' with the solutions I found so far. I wonder if any of you have a more elegant answer or suggestion (or can explain why this may be 'as good as it gets'). Thanks in advance!

所以,这里的设置:

public class Wishlist
{
    public Wishlist() { Wishitems = new List<Wishitem>(); }

    public long WishListId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Wishitem> Wishitems { get; set; }
}
public class Wishitem
{
    public long WishitemId { get; set; }
    public string Name { get; set; }
    public int Quantity { get; set; }
}

控制器:

public class WishlistsController : Controller
{
    private SandboxDbContext db = new SandboxDbContext();
    /* ... */
    public ActionResult Edit(long id)
    {
        Wishlist wishlist = db.Wishlists.Find(id);
        return View(wishlist);
    }

    [HttpPost]
    public ActionResult Edit(Wishlist wishlist)
    //OR (see below): Edit(Wishlist wishlist, ICollection<Wishitem> wishitems)
    {
        if (ModelState.IsValid)
        {
            db.Entry(wishlist).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(wishlist);
    }
    /* ... */
}

视图:浏览次数\\收藏\\ Edit.cshtml

@model Sandbox.Models.Wishlist
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Wishlist</legend>
        @Html.HiddenFor(model => model.WishListId)
        <div class="editor-label">@Html.LabelFor(model => model.Name)</div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
    </fieldset>
    <table>
        <tr>
            <th>
                Quantity
            </th>
            <th>
                Name
            </th>
        </tr>
        @for (var itemIndex = 0; itemIndex < Model.Wishitems.Count; itemIndex++)
  {
            @Html.EditorFor(item => Model.Wishitems.ToList()[itemIndex])
  }
    </table>
    <p>
        <input type="submit" value="Save" />
    </p>
}

的编辑模板:浏览次数\\共享\\ EditorTemplates \\ Wishitem.cshtml

@model Sandbox.Models.Wishitem
<tr>
    <td>
        @Html.HiddenFor(item=>item.WishitemId)
        @Html.TextBoxFor(item => item.Quantity)
        @Html.ValidationMessageFor(item => item.Quantity)
    </td>
    <td>
        @Html.TextBoxFor(item => item.Name)
        @Html.ValidationMessageFor(item => item.Name)
    </td>
</tr>

这是怎么回事?

上面的设置生成标准输入元素的页面为父收藏模型:

What is Going on?

The setup above generates a page with standard input elements for the 'parent' Wishlist model:

<input class="text-box single-line" id="Name" name="Name" type="text" value="MyWishlist" />  

对于儿童在表中Wishitems,我们获得索引输入元素:

For the 'children' Wishitems in the table, we get indexed input elements:

<input data-val="true" data-val-number="The field Quantity must be a number." data-val-required="The Quantity field is required." name="[0].Quantity" type="text" value="42" />
<input name="[0].Name" type="text" value="Unicorns" />

这导致了收藏心愿参数发送回一个空的 .Wishitems 属性。

This leads to a the Wishlist wishlist argument POSTed back with an empty .Wishitems property.

为POST处理器( [HttpPost]公众的ActionResult编辑(收藏心愿,ICollection的&LT; Wishitem&GT; wishitems))的替代签名还是让我一个空的 wishlist.Wishitems ,但让我访问(可能已修改) wishitems

The alternative signature for the POST handler ([HttpPost] public ActionResult Edit(Wishlist wishlist, ICollection<Wishitem> wishitems)) still gets me an empty wishlist.Wishitems, but lets me access the (potentially modified) wishitems.

在此第二种情况下,我可以自定义绑定的做一些。例如(不是最优雅code,我在我的职业生涯所示):

In this second scenario, I can do some for of custom binding. For instance (not the most elegant code I've seen in my career):

[HttpPost]
public ActionResult Edit(Wishlist editedList, ICollection<Wishitem> editedItems)
{
    var wishlist = db.Wishlists.Find(editedList.WishListId);
    if (wishlist == null) { return HttpNotFound(); }

    if (ModelState.IsValid)
    {
        UpdateModel(wishlist);

        foreach (var editedItem in editedItems)
        {
            var wishitem = wishlist.Wishitems.Where(wi => wi.WishitemId == editedItem.WishitemId).Single();
            if (wishitem != null)
            {
                wishitem.Name = editedItem.Name;
                wishitem.Quantity = editedItem.Quantity;
            }
        }
        db.SaveChanges();
        return View(wishlist);
    }
    else
    {
        editedList.Wishitems = editedItems;
        return View(editedList);
    }
}

我的收藏

我希望有我得到所有在一个单一的结构化对象,如已发布数据的方式:

My Wishlist

I wish there was a way for me to get all the POSTed data in a single structured object, eg:

[HttpPost]
public ActionResult Edit(Wishlist wishlist) { /* ...Save the wishlist... */ }

使用 wishlist.Wishitems 充满(可能已修改)项目

With wishlist.Wishitems filled with the (potentially modified) items

还是我来处理数据的合并,如果我的控制器必须单独收到他们一个更优雅的方式。就像是

Or a more elegant way for me to handle the merging of the data, if my controller must receive them separately. Something like

[HttpPost]
public ActionResult Edit(Wishlist editedList, ICollection<Wishitem> editedItems)
{
    var wishlist = db.Wishlists.Find(editedList.WishListId);
    if (wishlist == null) { return HttpNotFound(); }

    if (ModelState.IsValid)
    {
        UpdateModel(wishlist);
        /* and now wishlist.Wishitems has been updated with the data from the Form (aka: editedItems) */
        db.SaveChanges();
        return View(wishlist);
    }
    /* ...Etc etc... */
}

提示,技巧,想法?

Hints, tips, thoughts?


  • 这是一个沙盒的例子。我工作的实际应用是完全不同的,无关与沙盒暴露域。

  • 我不使用'的ViewModels的例子,因为 - 所以远他们似乎并不是答案的一部分。如果他们需要,我一定会介绍他们(在我的工作,我们的真正的应用程序已经在使用它们)。

  • 同样,库是由在这个例子中,简单的SandboxDbContext类抽象,但可能会通过一个通用的信息库和单位在真正的应用程序工作模式所取代。

  • 沙盒应用程序是使用内置:

    • 的Visual Web Developer 2010防爆preSS

      • 修复微软的Visual Web Developer 2010学习前preSS - ENU(KB2547352)

      • 修复微软的Visual Web Developer 2010学习前preSS - ENU(KB2548139)

      • 微软的Visual Web Developer 2010学习前preSS - ENU的Service Pack 1(KB983509)


      • 的意见剃刀语法

      • code-First方法

      • "Getting Started with ASP.NET MVC3" Covers the basics, but does not deal with model relationships

      入门使用MVC EF
      AN-ASP净MVC应用程序
      特别是<一个href=\"http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-\"相对=nofollow>第6 显示了如何处理一些模型之间的关系。
      然而,本教程采用的是的FormCollection 参数为它的POST处理程序,而不是自动模型绑定。
      换一种说法:
      [HttpPost]公众的ActionResult编辑(INT ID,的FormCollection的FormCollection)
      而不是沿着东西线
      [HttpPost]公众的ActionResult编辑(InstructorAndCoursesViewModel视图模型)
      此外,与给定的讲师相关课程的列表是重新presented(在UI)为一组具有相同名称的复选框(导致的String []的参数为POST处理程序),而不是想象中的那么我在看相同的情况。

      "Getting Started with EF using MVC" an-asp-net-mvc-application In particular Part 6 shows how to deal with some of the relationships between the models. However, this tutorial uses a FormCollection argument for its POST handler, rather than the automatic model binding. In other words: [HttpPost] public ActionResult Edit(int id, FormCollection formCollection) Rather than something along the lines of [HttpPost] public ActionResult Edit(InstructorAndCoursesViewModel viewModel) Also, the list of Courses associated with a given Instructor is represented (in the UI) as a set of checkboxes with the same name (leading to a string[] argument for the POST handler), not quite the same scenario that I am looking at.

      编辑可变长度的名单,ASP.NET MVC2式
      基于MVC2(所以我想,如果它仍然是描述现在我们已经MVC3最好的选择)。
      诚然,我没有(还)得到了处理从列表中插入和/或删除儿童模型。
      此外,该解决方案:

      "Editing a variable length list, ASP.NET MVC2-style" Based on MVC2 (so I'm wondering if it is still describes the best option now that we have MVC3). Admittedly, I have not (yet) got to dealing with the insertions and/or removal of Children models from the list. Also, this solution:


      • 依赖于定制code(BeginCollectionItem) - (但它仍然必要​​MVC3),这是罚款,如果有必要

      • 处理列表作为一个独立的集合,而不是包装模型的属性 - 换句话说,有围绕GiftsSet模式(等同于我的例子父收藏模型),虽然我不知道introduing明确父模型无效该解决方案或没有。

      <一个href=\"http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx\"相对=nofollow>ASP.NET电线格式模型绑定到数组,列表,集合,字典
      斯科特Hanselman的职位是被引用最多引用的儿子在MVC应用结合到列表的话题之一。
      不过,他只是描述由框架下通过,并用于生成符合操作方法的对象的命名约定(注意文章如何具有生成一个网页,然后提交数据所描述的行为之一的无例子)。
      这是伟大的信息,如果我们的必须的生成HTML自己。我们要不要?

      "ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries" Scott Hanselman's post is one of the most quoted reference son the topic of binding to lists in MVC applications. However, he is simply describing the naming conventions adopted by the framework and used to generate objects matching your action method (note how the article has no example of generating a page that then submits data to one of the actions described). This is great information if we have to generate the HTML ourselves. Do we have to?

      模式绑定到一个列表
      另一个顶部参照,通过菲尔哈克。它有一些相同的信息如上Hansleman后,也向我们展示了,我们可以在一个循环中使用HtmlHelpers(的for(int i = 0;我3;;我++){Html.TextBoxFor( M =&GT; M [​​] .title伪)} ),或在编辑模板( Html.EditorFor(M = GT; M [​​]))。
      但是,使用这种方法,由编辑模板生成的HTML将不包括任何具体的preFIX(例如:输入元素的名称和ID将在形式 [指数] .FieldName ,如: [0] .Quantity [1] .Name点)。这可能会或可能不会在本例中至关重要,但可能会在我的实际应用中的问题,在这里孩子们的不同的平行的名单可能会出现同样的观点。

      "Model Binding To A List" Another top reference, by Phil Haack. It has some of the same information as the Hansleman post above, but also shows us we can use HtmlHelpers within a loop (for (int i = 0; i < 3; i++) { Html.TextBoxFor(m => m[i].Title) }), or in an Editor Template (Html.EditorFor(m=>m[i])). However, using this approach, the HTML generated by the Editor Template would not include any specific prefix (eg: the names and ids of the input elements would be in the form [index].FieldName like: [0].Quantity, or [1].Name). This may or may not be critical in the example, but will probably be an issue in my actual application, where different 'parallel' lists of children may appear in the same view.

      推荐答案

      您可能要检查该链接的 HTTP://www.$c$ctuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx 我有类似的问题和上面让我去了解它。

      You may want to check this link http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx I had similar problem and the above allowed me to understand it

      这篇关于结合儿童的可编辑列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆