C# 实体框架及;ASP.NET MVC更复杂的模型

C# 实体框架及;ASP.NET MVC更复杂的模型,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,我有实体框架模型,其中包含对其他实体的引用,如 public class Product { [Key] public int ProductID { get; set; } [Required] public string Name { get; set; } [Required] public virtual Shop Shop { get; set; } [Required] public double Price {

我有实体框架模型,其中包含对其他实体的引用,如

public class Product
{
    [Key]
    public int ProductID { get; set; }

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

    [Required]
    public virtual Shop Shop { get; set; }

    [Required]
    public double Price { get; set; }
}
我想创建包含
Shop
选择器(下拉菜单)的编辑视图

默认情况下,我已经创建了连接实体模型的基本MVC控制器,它创建了如下编辑:

public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    Product product = db.Products.Find(id);

    if (product == null)
    {
        return HttpNotFound();
    }
    return View(product);
}
和视图不包含商店选择器

我尝试添加下拉列表,如:

@Html.DropDownListFor(product => product.Shop, (SelectList)ViewBag.Shops)
但在POST方法中,商店实体为空

如何处理呢?

我希望这能有所帮助

产品型号:

public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public int ShopID { get; set; }
    public double Price { get; set; }
}
public class ProductViewModel
{
    public Product Model { get; set; }
    public IEnumerable<SelectListItem> Shops{ get; set; }

    public ProductViewModel()
    {
         GetShops();
    }

    public void GetShops()
    {
        Shops = new List<SelectListItem>();

        var collectionShops = GetShopsFromDatabase();
        Shops.AddRange(
                collectionShops.Select(
                    contract =>
                    new SelectListItem
                    {
                        Text = contract.ShopDescription,
                        Value = contract.ShopID.ToString()
                    }));
    }
}
然后是产品的ViewModel:

public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public int ShopID { get; set; }
    public double Price { get; set; }
}
public class ProductViewModel
{
    public Product Model { get; set; }
    public IEnumerable<SelectListItem> Shops{ get; set; }

    public ProductViewModel()
    {
         GetShops();
    }

    public void GetShops()
    {
        Shops = new List<SelectListItem>();

        var collectionShops = GetShopsFromDatabase();
        Shops.AddRange(
                collectionShops.Select(
                    contract =>
                    new SelectListItem
                    {
                        Text = contract.ShopDescription,
                        Value = contract.ShopID.ToString()
                    }));
    }
}

创建视图模型以表示要显示的内容

public class ProductVM
{
  public int ProductID { get; set; }
  [Required]
  public string Name { get; set; }
  [Required]
  public int? ShopID { get; set; }
  [Required]
  public double Price { get; set; }
  public SelectList ShopList { get; set; }
}
在控制器中,将模型映射到视图模型

public ActionResult Edit(int? ID)
{
  ....
  Product product = db.Products.Find(id);
  ProductVM model = new ProductVM();
  // map properties
  ....
  // populate select list (assumes Shop has properties ID and Name)
  model.ShopList = new SelectList(db.Shops, "ID", "Name");
  return View(product);
}
在你看来

@model ProductVM
....
@Html.DropDownListFor(m => m.ShopID, Model.ShopList, "--Select shop--")
@Html.ValidationMessageFor(m -> m.ShopID)
这将使用选定的店铺ID发回模型<代码>选择控制回发单个值,因此您无法回发复杂对象,如
商店
。POST方法将是

[HttpPost]
public ActionResult Edit(ProductVM model)
{
  ....
}

注意:您可以使用一些工具,例如使映射更容易

首先,
产品
是与EF相关的数据模型,不应更改。这就是我们使用视图模型的原因。其次,视图模型应该包含与视图相关的属性,而不是方法,当然也不是数据库代码。这是控制器的责任。您可以添加POST方法在这种情况下的外观吗?我的意思是,如果我的实体模型属性Shop中有,并且我的viewModel属性ShopID中有,我需要编写方法将VM转换回模型,如:
Shop=db.Shops.Find(this.ShopID)
?正确的?