TL; DR :在我的ASP.NET MVC3应用程序中,我应该如何实现一个允许我编辑父母'的详细信息的视图。实体同时作为“孩子”列表的详细信息。实体?
更新 :我接受了@torm's answer,因为他提供了a link,说明了为什么我目前解决方案可能会得到很好的解决方案。 但是,我们很乐意听到其他人有其他选择!
我一直在搜索和阅读(到目前为止的一些调查结果,请参阅底部的'参考文献'部分)。 但是,我仍然觉得有什么东西可以闻到'臭到目前为止我找到的解决方案。我想知道你们中是否有人有更优雅的答案或建议(或者可以解释为什么这可能是“和它一样好”#39;)。 提前致谢!
所以,这是设置:
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);
}
/* ... */
}
@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>
}
@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>
上面的设置生成一个页面,其中包含“父母”的标准输入元素。愿望清单模型:
<input class="text-box single-line" id="Name" name="Name" type="text" value="MyWishlist" />
对于孩子们来说&#39;表中的Wishitems,我们得到索引输入元素:
<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" />
这会导致Wishlist wishlist
参数以空.Wishitems
属性发回。
POST处理程序的替代签名([HttpPost] public ActionResult Edit(Wishlist wishlist, ICollection<Wishitem> wishitems)
)仍然为空wishlist.Wishitems
,但让我访问(可能已修改)wishitems
。
在第二种情况下,我可以做一些自定义绑定。例如(不是我职业生涯中见过的最优雅的代码):
[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);
}
}
我希望有一种方法可以将所有POSTed数据放在一个结构化对象中,例如:
[HttpPost]
public ActionResult Edit(Wishlist wishlist) { /* ...Save the wishlist... */ }
wishlist.Wishitems
填充(可能已修改的)项目
如果我的控制器必须单独接收数据,或者我可以更优雅地处理数据的合并。就像是
[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... */
}
提示,提示,想法?
"Getting Started with ASP.NET MVC3" 涵盖基础知识,但不涉及模型关系
"Getting Started with EF using MVC"
AN-ASP净MVC应用程序
特别是Part 6显示了如何处理模型之间的一些关系。
但是,本教程对其POST处理程序使用FormCollection
参数,而不是自动模型绑定。
换一种说法:
[HttpPost] public ActionResult Edit(int id,FormCollection formCollection)
而不是某些东西
[HttpPost] public ActionResult Edit(InstructorAndCoursesViewModel viewModel)
此外,与给定教师关联的课程列表(在UI中)表示为一组具有相同名称的复选框(导致POST处理程序的string[]
参数),与我不完全相同的情况我在看。
"Editing a variable length list, ASP.NET MVC2-style" 基于MVC2(所以我想知道它是否仍然描述了我们拥有MVC3的最佳选择)。 不可否认,我还没有(还)处理从名单中插入和/或删除儿童模型的问题。 此外,这个解决方案:
"ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries" Scott Hanselman的帖子是MVC应用程序中绑定到列表主题的最引用的参考儿子之一。 但是,他只是简单地描述框架采用的命名约定,并用于生成与您的操作方法匹配的对象(请注意文章没有生成页面的示例,然后将数据提交到所描述的操作之一)。 如果我们必须自己生成HTML,这是很好的信息。我们必须吗?
"Model Binding To A List"
Phil Haack的另一个热门参考。它有一些与上面Hansleman帖子相同的信息,但也向我们展示了我们可以在循环(for (int i = 0; i < 3; i++) { Html.TextBoxFor(m => m[i].Title) }
)或编辑器模板(Html.EditorFor(m=>m[i])
)中使用HtmlHelpers。
但是,使用此方法,编辑器模板生成的HTML将不包含任何特定前缀(例如:输入元素的名称和ID将采用[index].FieldName
形式,如:[0].Quantity
或{ {1}})。这在示例中可能或可能不是关键,但在我的实际应用中可能是一个问题,其中不同的并行&#39;儿童名单可能出现在同一视图中。
答案 0 :(得分:1)
您可能需要查看此链接http://www.codetuning.net/blog/post/Binding-Model-Graphs-with-ASPNETMVC.aspx我遇到了类似的问题,上面的内容让我理解了它