Scaffolding ModelView创建基础数据库表

时间:2013-12-29 19:00:34

标签: c# asp.net-mvc asp.net-mvc-4 viewmodel

我第一次尝试使用ViewModels使用AutoMapper。我有两个模型:

public class Item
{
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemOption> ItemOptions { get; set; }
    //...
}

public class ItemOption
{
    public int ItemOptionId { get; set; }
    public string Name { get; set; }
    public string Barcode { get; set; }
    //...
}

我已经变成了两个ViewModel:

public class ItemDetailViewModel
{
    public int ItemDetailViewModelId { get; set; }
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemDetailItemOptionViewModel> ItemOptions { get; set; }
}

public class ItemDetailItemOptionViewModel
{
    public int ItemDetailItemOptionViewModelId { get; set; }
    public int ItemOptionId { get; set; }
    public string Name { get; set; }
    public string Barcode { get; set; }

}

然后我在应用程序启动时设置了以下内容:

Mapper.CreateMap<Item, ItemDetailViewModel>();
Mapper.CreateMap<ItemOption, ItemDetailItemOptionViewModel>();

最后我搭建了我的ItemDetailViewModel:

enter image description here

然后我构建了我的项目并通过/ Item / Create

添加了一个新项目

我在数据库中看到期望看到我在Item表中有一个条目,但我有ItemDetailViewModel和ItemDetailItemOptionViewModel表,我没想到,数据是ItemDetailViewModel。

我认为我的脚手架做错了什么?如何在不将其作为主要业务模型的一部分的情况下构建ViewModel?

更多详情

如果无法使用ViewModel搭建控制器,那么如何在控制器中引用ViewModel并将更改保存回数据库?

例如,一旦我从db上下文中删除ItemDetailViewModel,会有什么改变?

    //
    // POST: /Item/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ItemDetailViewModel itemdetailviewmodel)
    {
        if (ModelState.IsValid)
        {
            db.ItemDetailViewModels.Add(itemdetailviewmodel);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(itemdetailviewmodel);
    }

更多详情[2]

所以我更正确的是我的索引/详细信息应该如此工作还是有更好的方法呢?

    //
    // GET: /Item/

    public ActionResult Index()
    {
        var items = db.Items.ToList();
        var itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(items);
        return View(itemdetailviewmodel);
    }

    //
    // GET: /Item/Details/5

    public ActionResult Details(int id = 0)
    {
        ItemDetailViewModel itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(db.Items.Find(id));
        if (itemdetailviewmodel == null)
        {
            return HttpNotFound();
        }
        return View(itemdetailviewmodel);
    }

1 个答案:

答案 0 :(得分:1)

脚手架并不那么聪明。标准控制器脚手架模板正在使用控制器模型创建DbContext,并假设您正在使用数据库模型,而不是视图模型,并且它不使用自动映射。所以你需要不使用脚手架,或者在使用脚手架之前检查它是做什么的。

使用脚手架的方式没有任何问题,只是不应该做你期望的事情。

更新这是您在没有脚手架的情况下执行此操作的方法

// Without Automapper
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ItemDetailViewModel model)
{
    if (ModelState.IsValid)
    {
        var item = new Item() 
        {
            Active = model.Active,
            ItemCode = model.ItemCode,
            Name = model.Name,
            ItemOptions = // code to convert from List<ItemDetailItemOptionViewModel> to List<ItemOption>
        }
        db.Items.Add(item);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(model);
}


// with Automapper - not recommended by author of Automapper
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ItemDetailViewModel model)
{
    if (ModelState.IsValid)
    {
        var item = Automapper.Mapper.Map<Item>(model);

        db.Items.Add(item);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(model);
}    

您需要修改DbContext以使IDbSet<Item> Items代替IDbSet<ItemDetailViewModels> ItemDetailViewModels

创建Automapper是为了从域模型映射到视图模型而不是其他方式。我已经做了一段时间,但这很麻烦,并导致细微的错误和其他维护问题。甚至吉米·博加德本人says you should not map from view models to domain models