我正在使用VS 2013开发ASP.NET MVC 5,EF 6,Razor Engine,VB语言和数据库第一种方法.
现在,在我的数据库中; 我有两个表格如下:
CREATE TABLE [dbo].[Group] ( [Id] INT NOT NULL PRIMARY KEY IDENTITY(1, 1), [Name] VARCHAR(50) NOT NULL )
和
CREATE TABLE [dbo].[Subscriber] ( [Id] INT NOT NULL PRIMARY KEY IDENTITY(1, 1), [FirstName] [nvarchar](100) NOT NULL, [MiddleName] [nvarchar](100) NULL, [LastName] [nvarchar](100) NOT NULL, [Email] [varchar] (200) NOT NULL UNIQUE, [GroupId] INT NULL REFERENCES [Group] ON DELETE SET NULL )
现在,当我使用脚手架自动生成控制器和视图时; 我Group
在"创建订阅者"和"编辑订阅者"视图中得到一个
但实际上,我希望"创建组"和"编辑组"视图向我询问我Subscribers
想要添加到特定组中.对于相同的HTML控制可以是复选框的列表或<选择多个="多个">与所有Subscriber
的项目,如<选项>秒.
我该如何自动生成/实现它?
不要过分依赖脚手架.重点在于它为您提供了工作的基础; 对你的观点来说,这不是万能的.您可以而且应该修改脚手架以满足您的需求,老实说,通常情况下,从头开始比尝试撤消脚手架增加的所有不必要的绒毛更容易.
也就是说,特别是在一次选择多个相关项目时,您需要一个视图模型.试图使用你的实体来快速耗尽.所以创建一个类,如:
public class GroupViewModel { // `Group` properties you need to edit here public List<int> SelectedSubscriberIds { get; set; } public IEnumerable<SelectListItem> SubscriberChoices { get; set; } }
然后,在你的控制器中:
// We'll use this code multiple times so it's factored out into it's own method private void PopulateSubscriberChoices(GroupViewModel model) { model.SubscriberChoices = db.Subscribers.Select(m => new SelectListItem { Value = m.Id.ToString(), Text = m.FirstName + " " + m.LastName }); } public ActionResult Create() { var model = new GroupViewModel(); PopulateSubscriberChoices(model); return View(model); } [HttpPost] public ActionResult Create(GroupViewModel model) { if (ModelState.IsValid) { // Map the posted values onto a new `Group` instance. To set `Subscribers`, // lookup instances from the database using the list of ids the user chose var group = new Group { Name = model.Name, Subscribers = db.Subscribers.Where(m => model.SelectedSubscriberIds.Contains(m.Id)) }; db.Groups.Add(group); db.SaveChanges() return RedirectToAction("Index"); } PopulateSubscriberChoices(model); return View(model); } public ActionResult Edit(int id) { var group = db.Groups.Find(id); if (group == null) { return new HttpNotFoundResult(); } // Map `Group` properties to your view model var model = new GroupViewModel { Name = group.Name, SelectedSubscriberIds = group.Subscribers.Select(m => m.Id).ToList() }; PopulateSubscriberChoices(model); return View(model); } [HttpPost] public ActionResult Edit(int id, GroupViewModel model) { var group = db.Groups.Find(id); if (group == null) { return new HttpNotFoundResult(); } if (ModelState.IsValid) { group.Name = model.Name; // Little bit trickier here // First remove subscribers that are no longer selected group.Subscribers.Where(m => !model.SelectedSubscriberIds.Contains(m.Id)) .ToList().ForEach(m => group.Subscribers.Remove(m)); // Now add newly selected subscribers var existingSubscriberIds = group.Subscribers.Select(m => m.Id); var newSubscriberIds = model.SelectedSubscriberIds.Except(existingSubscriberIds); db.Subscribers.Where(m => newSubscriberIds.Contains(m.Id)) .ToList().ForEach(m => group.Subscribers.Add(m)); db.Entry(group).State = EntityState.Modified; db.SaveChanges() return RedirectToAction("Index"); } PopulateSubscriberChoices(model); return View(model); }
编辑后期操作是最困难的.为了不会出现有关重复键等的错误,您需要确保不要将重复项添加到集合中.您还需要确保删除此组与用户取消选择的任何项之间的关系.除此之外,它非常直接.
最后在您的视图中,您只需要渲染选择列表:
@model Namespace.To.GroupViewModel ... @Html.ListBoxFor(m => m.SelectedSubscriberIds, Model.SubscriberChoices)
UPDATE
添加转换的VB代码.这可能无法100%开箱即用.任何具有更多VB经验的人都可以随意编辑以纠正任何问题.
查看模型
Public Class GroupViewModel ' Group properties you need to edit here Public Property SelectedSubscriberIds As List(Of Integer) Public Property SubscriberChoices As IEnumerable(Of SelectListItem) End Class
控制器代码
' We'll use this code multiple times so it's factored out into it's own method Private Sub PopulateSubscriberChoices(model As GroupViewModel) model.SubscriberChoices = db.Subscribers.[Select](Function(m) New SelectListItem With { _ .Value = m.Id, _ .Text = m.FirstName & " " & m.LastName _ }) End Sub Public Function Create() As ActionResult Dim model as New GroupViewModel PopulateSubscriberChoices(model) Return View(model) End Function <HttpPost> _ Public Function Create(model As GroupViewModel) As ActionResult If ModelState.IsValid Then ' Map the posted values onto a new `Group` instance. To set `Subscribers`, ' lookup instances from the database using the list of ids the user chose Dim group = New Group With { _ .Name = model.Name, _ .Subscribers = db.Subscribers.Where(Function(m) model.SelectedSubscriberIds.Contains(m.Id)) _ } db.Groups.Add(group) db.SaveChanges() Return RedirectToAction("Index") End If PopulateSubscriberChoices(model) Return View(model) End Function Public Function Edit(id As Integer) As ActionResult Dim group = db.Groups.Find(id) If group Is Nothing Then Return New HttpNotFoundResult() End If ' Map `Group` properties to your view model Dim model = New GroupViewModel With { _ .Name = group.Name, _ .SelectedSubscriberIds = group.Subscribers.[Select](Function(m) m.Id).ToList _ } PopulateSubscriberChoices(model) Return View(model) End Function <HttpPost> _ Public Function Edit(id As Integer, model As GroupViewModel) As ActionResult Dim group = db.Groups.Find(id) If group Is Nothing Then Return New HttpNotFoundResult() End If If ModelState.IsValid Then group.Name = model.Name ' Little bit trickier here ' First remove subscribers that are no longer selected group.Subscribers.Where(Function(m) Not model.SelectedSubscriberIds.Contains(m.Id)).ToList().ForEach(Function(m) group.Subscribers.Remove(m)) ' Now add newly selected subscribers Dim existingSubscriberIds = group.Subscribers.[Select](Function(m) m.Id) Dim newSubscriberIds = model.SelectedSubscriberIds.Except(existingSubscriberIds) db.Subscribers.Where(Function(m) newSubscriberIds.Contains(m.Id)).ToList().ForEach(Function(m) group.Subscribers.Add(m)) db.Entry(group).State = EntityState.Modified db.SaveChanges() Return RedirectToAction("Index") End If PopulateSubscriberChoices(model) Return View(model) End Function