gpt4 book ai didi

c# - MVC 5:ViewModel/创建的传递列表

转载 作者:行者123 更新时间:2023-11-30 20:35:49 26 4
gpt4 key购买 nike

因此,我目前正在研究和分析ViewModels的使用。

在我的应用程序(所谓的“餐厅”)中,我希望我的“用户”能够创建菜单。

当他们想要创建菜单时:他们可以选择名称+可以加入菜单的人数。但是,他们也可以添加餐厅中已有的菜肴。这将是复选框的样式,最后是“创建”按钮。

这意味着我必须使用ViewModel。我目前正在尝试为创建菜单添加菜肴列表的可能性。但是我被困在for循环中,该循环用于遍历所有菜肴。或者更好的是,我被整个概念所困扰:


将所有已经创建的菜肴显示到CreateMenu视图的最佳方法是什么?如果我将它们添加到ViewBag中,是否仍然可以遍历ViewBag?
可以说我成功地尝试了自己想做的事。如何从ViewModel创建一个基于(或提取?)的新Menu?


在我的代码中,请注意,不能真正更改菜单-模型,因为我已经使用了菜单中的菜肴列表(在另一个视图中,我在其中显示所有菜单及其菜式)。

也忽略了错误名称或数据拼写错误的可能性,因为我翻译了佛兰德语中的所有内容

楷模

public class Menu
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Range(0,10)]
public int AmountPersons { get; set; }
[Range(0,double.MaxValue)]
public double Price { get; set; }
public virtual List<Dish> Dishes { get; set; }
}

public class Dish
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public enum Types { VOORGERECHT, HOOFDGERECHT, DRANK, DESSERT}
public Types Type { get; set; }
public double Price { get; set; }
public virtual List<Menu> Menus { get; set; }
public virtual List<Table> Tables { get; set; }
//Checked used for the 'checkbox' in the CreateMenu-View
[NotMapped]
public bool Checked { get; set; }
}

public class MenuViewModel
{
public Menu Menu { get; set; }
public List<Dish> AddedDishes { get; set; }
}


控制者

public ActionResult CreateMenu( )
{
MenuViewModel gm = new MenuViewModel();
// Assign ALL already created dishes to the list that the user can choose.
// AddedDishes is wrong? ViewBag preferred?
gm.AddedDishes = db.Dishes.ToList();
return View(gm);
}

// Add the Menu to all the Menu's in the Database.
[HttpPost]
public ActionResult MenuAanmaken(MenuModel gm)
{
// code to save the menu with all the added dishes to the database
// Conflict!? Cannot convert the MenuViewModel to the Menu-model How do we need to extract the Menu and the AddedDishes list
// to a menu and save that one to the database?
db.Menus.Add(gm);
return View(gm);
}


视图

@using VBExamen.Models
@model MenuViewModel
....

@Html.LabelFor(m => m.Menu.Name)
@Html.EditorFor(m => m.Menu.Name)
@Html.LabelFor(m => m.Menu.AmountPersons)
@Html.EditorFor(m => m.Menu.AmountPersons)

@for(int i = 0; i < Model.AddedDishes.Count; i++)
{
<tr>
<td>
@Html.DisplayFor( .Name)
@Html.HiddenFor(item => .Id)
@Html.CheckBoxFor(item => .Checked)
</td>
</tr>
}


E D I T E D _ U P D A T E(请参阅下文)
好吧,我想我现在要走了,

我对课程进行了如下编辑:

public class MenuViewModel<T>
{
public Menu Menu { get; set; }
public List<T> DishList { get; set; }
public MenuViewModel()
{
this.Lijst = new List<T>();
}
}


控制者

public ActionResult CreateMenu(MenuViewModel<Dish> model )
{
model.DishList = db.Gerechten.ToList();
return View(model);
}

[HttpPost]
public ActionResult CreateMenu(MenuViewModel<Dish> model,List<Gerecht> SelectedList)
{
Menu t = new Menu();
t.Naam = gm.Menu.Naam;
t.AmountPersons = gm.Menu.AmountPersons;
t.Dishes = SelectedList;
db.Menus.Add(t);
return View("Menus", model);
}


查看功能创建列表

@for (int i = 0; i < Model.DishList.Count(); i++)
{
<tr>
<td>
@Html.Label(Model.DishList[i].Naam)
<input type="hidden" name=@String.Format("DishList[{0}].Id", i) value=@Model.DishList.ElementAt(i).Id />
<input type="hidden" name=@String.Format("DishList[{0}].Name", i) value=@Model.DishList.ElementAt(i).Name />
<input type="checkbox" name=@String.Format("DishList[{0}].value", i) />
<input type="hidden" name=@String.Format("DishList[{0}].value", i) value="false" />
</td>
<br />
</tr>
}


在观看了有关ViewModels的10篇教程之后,我做到了这一点,我的下一种方法是否比第一种更好?

我想是因为我在屏幕上看到以下内容:

enter image description here

我在想下一种方法。我正在考虑比较2个列表(1个视图模型,1个已通过)并查看复选框状态?

更新

在斯蒂芬·穆克(Stephen Muecke)回答之后,我重新编辑了代码,但发现了一个我似乎无法理解的问题。

答案说我应该以类的形式处于一对多表的位置:

// You have not indicated the 1-many table the dishes are saved to so adjust as required
MenuDish dish = new MenuDish()
{
MenuId = menu.ID,
DishId = dish
};
db.MenuDishes.Add(dish);


但是,我们在学校中学到的是,如果您在实体的数据模型中创建列表,则链接表将在数据库中自动生成。这正是我的数据库所做的(不创建MenuDish类):

MenuGerechts代表MenuDish。
这是由实体框架自动创建的表。
enter image description here
这给我带来了以下问题。我已将控制器重新编辑为以下内容:

 [HttpPost]
public ActionResult MenuAanmaken(MenuVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}

IEnumerable<int> selectedDishes = model.Dishes.Where(x => x.IsSelected).Select(x => x.ID);
Menu menu = new Menu()
{
Naam = model.Name,
AantalPersonen = model.AmountPersons
};

foreach (int id in selectedDishes)
{
Dish g = db.Dishes.Find(id);
menu.Dishes.Add(g);

};

db.Menus.Add(menu);
db.SaveChanges();

return RedirectToAction("Menus", "Menu");
}


我收到 Object reference not set to an instance of an object错误,并且我理解为什么。

自从数据模型菜单(已经有一个菜品清单)以来,我已经进行了更改。但是,假设有S. Muecke的答案,这不是解决此ViewModel的正确方法,因为他提出了使用New Class(它是为支持一对多关系而创建的)的使用?

这使我得出以下问题的结论:


为什么不可能或不建议直接将所选菜肴添加到菜单实例中?
是否总是需要在数据模型中的表'MenuDish'之间创建中间表?
创建新的菜单后,以下代码是否仍然可以工作(显示菜单及其菜肴)?:


控制器:

   public ActionResult Menus()
{
List<Menu> menus = db.Menus.ToList();
return View(menus);
}


视图:

@model IEnumerable<VBExamen.Models.Menu>

@{
ViewBag.Title = "Menus";
}

<h2>Menus</h2>

<p>
@Html.ActionLink("Create New Menu", "CreateMenu")
</p>

@foreach (var item in Model)
{
<table>


<ul>
<p>@Html.DisplayFor(modelItem => item.Name)</p>

@foreach (var g in item.Dishes)
{
<li>
@Html.DisplayFor(modelItem => g.Name)
</li>
}
</ul>
</table>
}


输出以下内容:

enter image description here

什么是这样做的良好动力?

更新2

因此,我在项目中包含以下内容:
**我使用了 Table()-注释,使其使用已经创建的注释**


**型号:**

[Table(“ MenuGerechts”)]
    公共课程MenuGerechts
    {
        [键]
        [ForeignKey(“ Menu”)]
        公共虚拟诠释? MenuId {get;组; }
        公用虚拟菜单Menu {get;组; }

    [ForeignKey("Dish")]
public virtual int? DishId { get; set; }
public virtual Dish Dish { get; set; }
}



然后,我实际上已经成功创建了新菜单!但是,当我转到概述菜单页面时(如上图所示),它仅显示菜单名称,而不显示菜单中包含的餐单。

但是,数据库不允许我的MenuDish链接表用于新创建的类(它创建了一个新类,并使用“旧”菜单重命名了旧类,并在其后带有“ 1”:

enter image description here

因此,为什么我要问以前的问题。这是否意味着我整个练习的方法是错误的?

新问题:
我的menuCreate ViewModel仅在选择1个菜的情况下有效吗?为什么会这样呢?我收到以下错误 The role 'MenuGerechts_Menu_Source' of the relationship 'VBExamen.Models.MenuGerechts_Menu' has multiplicity 1 or 0..1.

最佳答案

首先,视图模型不应包含作为数据模型的属性。它应该只包含您在视图中显示/编辑的属性,建议您阅读What is ViewModel in MVC?

根据所显示表单的图像,需要使用视图模型(为简单起见,省略了显示和验证属性)

public class MenuVM
{
public int? ID { get; set; } // included so this can be used for editing as well as creating
public string Name { get; set; }
public int AmountPersons { get; set; }
public List<DishVM> Dishes { get; set; }
}
public class DishVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}


和控制器的GET方法

public ActionResult CreateMenu( )
{
// Get all the dishes from the database
var dishes = db.Dishes; // modify to suit
// Initialize the view model
var model = new MenuVM()
{
Dishes = dishes.Select(x => new DishVM()
{
ID = x.Id,
Name = x.Name
}).ToList()
};
return View(model);
}


然后在视图中(为简单起见,省略了 LabelFor()ValidationFor()方法)

@model MenuVM
@using (Html.BeginForm())
{
@Html.TextBoxFor(m => m.Name)
@Html.TextBoxFor(m => m.AmountPersons )
for(int i = 0; i < Model.Dishes.Count; i++)
{
<div>
@Html.HiddenFor(m => m.Dishes[i].ID)
@Html.HiddenFor(m => m.Dishes[i].Name)
@Html.CheckBoxFor(m => m.Dishes[i].IsSelected)
@Html.LabelFor(m => m.Dishes[i].IsSelected, Model.Dishes[i].Name)
</div>
}
<input type="submit" value="Create" />
}


最后POST方法将是

public ActionResult CreateMenu(MenuVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Initialize and save the Menu
Menu menu = new Menu()
{
Name = model.Name,
AmountPersons = model.AmountPersons
};
db.Menus.Add(menu);
db.SaveChanges(); // you now have the ID of the new menu
// Save the dishes associated with the menu
IEnumerable<int> selectedDishes = model.Dishes.Where(x => x.IsSelected).Select(x => x.ID);
foreach(int id in selectedDishes)
{
// You have not indicated the 1-many table the dishes are saved to so adjust as required
MenuDish dish = new MenuDish()
{
MenuId = menu.ID,
DishId = dish
};
db.MenuDishes.Add(dish);
}
db.SaveChanges(); // save the selected dishes
return RedirectToAction(...); // redirect somewhere
}


旁注:从数据模型中删除 [NotMapped] public bool Checked { get; set; }属性。

关于c# - MVC 5:ViewModel/创建的传递列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37579979/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com