C# 如何在asp.net mvc 5中通过视图创建/编辑模型

C# 如何在asp.net mvc 5中通过视图创建/编辑模型,c#,asp.net,asp.net-mvc,entity-framework,scaffolding,C#,Asp.net,Asp.net Mvc,Entity Framework,Scaffolding,我有一个关于我的模型的问题,你可以在下图中看到 如你们所见,我得到了3个实体,它们之间有1:n和m:n的关系 我希望我可以通过web界面编辑这些模型。因此,我构建了这三个模型(使用实体框架添加控制器),得到了edit/delete/create/视图,当然每个实体都有一个控制器 但是VS没有为关系自动创建输入/字段,所以我想手动实现它们。在我想这样做之前,是否有一种更简单的方法来实现/构建这个模型,这样我甚至可以编辑关系(复选框或(多)选择是最好的)? 提前谢谢 对于一个或多个,您可以在合作伙

我有一个关于我的模型的问题,你可以在下图中看到

如你们所见,我得到了3个实体,它们之间有1:n和m:n的关系

我希望我可以通过web界面编辑这些模型。因此,我构建了这三个模型(使用实体框架添加控制器),得到了
edit/delete/create/
视图,当然每个实体都有一个控制器

但是VS没有为关系自动创建输入/字段,所以我想手动实现它们。在我想这样做之前,是否有一种更简单的方法来实现/构建这个模型,这样我甚至可以编辑关系(复选框或(多)选择是最好的)?
提前谢谢

对于一个或多个,您可以在合作伙伴视图中为Tip使用DropDownList(请参阅。许多可以通过ViewModels和JavaScript框架(如Knockout)来处理。

不,这里的框架是故意不附带的,因为有许多不同的方法可以处理这个问题。也许您只想从选择列表中进行选择?也许您想要复选框,或者,您想在对于最后一个,您是想一次发布所有内容还是使用AJAX

因此,框架没有为您选择,而是将决策权留给您,因为只有您知道应用程序应该如何构建。不管怎样,依赖框架往往会让您感到痛苦。它们只在最基本和最理想的场景中工作,应用程序需求何时是基本或理想的?现在我甚至都不关心它们,我更喜欢手动创建我的控制器/视图。它最终比处理脚手架和撤销所有不适用的东西都要快

因此,由于您正在寻找选择框(单选或多选),首先,我建议为您的实体创建视图模型

public class TipViewModel
{
    [Required]
    public string Name { get; set; }

    [Required]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [Required]
    public int? SelectedPartnerId { get; set; }
    public IEnumerable<SelectListItem> PartnerChoices { get; set;}

    [Required]
    public int? SelectedBookId { get; set; }
    public IEnumerable<SelectListItem> BookChoices { get; set; }
}
我已经提取了填充这些选择列表的代码,因为该代码将在整个控制器中多次使用。此外,我在书籍的
文本
值上使用
string.Format
,只是为了表明您可以对选择列表项的文本执行任何操作。此外,上面的代码将用于cr很明显,执行eate操作。执行编辑类似,但略有不同:

public ActionResult Edit(int id)
{
    var tip = db.Tips.Find(id);
    if (tip == null)
    {
        return new HttpNotFoundResult();
    }

    var model = new TipViewModel
    {
        Name = tip.Name,
        Description = tip.Description,
        SelectedPartnerId = tip.Partner != null ? tip.Partner.Id : new int?(),
        SelectedBookId = tip.Book != null ? tip.Book.Id : new int?()
    }

    PopulateChoices(model);

    return View(model);
}
主要区别在于,您显然正在处理一个现有实例,因此需要从数据库中提取该实例。然后,您只需要将实体中的数据映射到视图模型上。同样,由于您没有明确的外键属性,因此您必须做一些额外的工作,以获得当前选择的
合作伙伴
/
Book
values,否则您可以直接复制外键属性的值。另外,在这里,我只是在手动映射,但有第三方库可以简化此任务(请参阅:)

这样,您就可以实现视图。一切都将与您直接使用实体时的工作方式相同,您只需进行一些修改。首先,您需要更改视图的模型声明:

@model Namespace.To.TipViewModel
然后,添加两个相关属性的选择列表:

@Html.DropDownListFor(m => m.SelectedPartnerId, Model.PartnerChoices)

...

@Html.DropDownListFor(m => m.SelectedBookId, Model.BookChoices)
有趣的事情发生在操作的后期版本中。大多数代码将与GET版本保持一致,但现在您将有一个
if(ModelState.IsValid)
块:

[HttpPost]
public ActionResult Create(TipViewModel model)
{
    if (ModelState.IsValid)
    {
        // map the data from model to your entity
        var tip = new Tip
        {
            Name = model.Name,
            Description = model.Description,
            Partner = db.Partners.Find(model.SelectedPartnerId),
            Book = db.Books.Find(model.SelectedBookId)
        }

        db.Tips.Add(tip);
        db.SaveChanges();

        return RedirectToAction("Index");
    }

    // Form has errors, repopulate choices and redisplay form

    PopulateChoices(model);

    return View(model);
}
编辑版本也是类似的,只是要映射到现有实例上,例如:

tip.Name = model.Name;
tip.Description = model.Description;
tip.Partner = db.Partners.Find(model.SelectedPartnerId);
tip.Book = db.Books.Find(model.SelectedBookId);
这就是引用属性的全部内容。在您的问题中,您的实体上实际上没有任何M2M甚至一对多的内容。所有内容都是一对一的,但如果您确实有集合属性,则需要稍微不同地处理它。您仍然需要视图模型上的属性来保存选定的值和e现有选择:

public List<int> SelectedFooIds { get; set; }
public IEnumerable<SelectListItem> FooChoices { get; set; }
并且,您需要对编辑操作的GET和POST版本进行更改。对于GET,您需要将集合属性压缩为ID列表:

var model = new TipViewModel
{
    ...
    SelectedFooIds = tip.Foos.Select(m => m.Id).ToList(),
}
在编辑版本中,您可以设置新的选定项目:

tip.Foos = db.Foos.Where(m => model.SelectedFooIds.Contains(m.Id);
最后,在视图中,您可以使用
ListBoxFor
而不是
DropDownListFor
来启用multiselect:

@Html.ListBoxFor(m => m.SelectedFooIds, Model.FooChoices)
+1-否决票被否决
tip.Foos = db.Foos.Where(m => model.SelectedFooIds.Contains(m.Id);
@Html.ListBoxFor(m => m.SelectedFooIds, Model.FooChoices)