3

我希望你能帮助我,我对 MVC 和实体框架很陌生,并试图理解它。我正在使用 MVC4 和 EF5。

这是我正在尝试做的事情的概述......

我有两个实体,Site 和 SiteType。每个站点可以有多个站点类型,因此它们具有多对多关系。我通过创建 3 个表、Site、SiteType 和 SiteSiteType 来设置具有典型多对多关系的数据库。SiteSiteType 仅包含 2 列,即 SiteId 和 SiteType Id。

我更新了实体模型,它完美地为站点创建了这样的实体......

public partial class Site
{
    public Site()
    {
        this.SiteTypes = new HashSet<SiteType>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public virtual ICollection<SiteType> SiteTypes { get; set; }
}

这对于 SiteType

public partial class SiteType
{
    public SiteType()
    {
        this.Sites = new HashSet<Site>();
    }    
    public int Id { get; set; }
    public string Name { get; set; }    
    public virtual ICollection<Site> Sites { get; set; }
}

现在我使用的是强类型视图,但是我没有使用 Site 作为类型,而是使用我创建的名为 SiteViewModel 的自定义 ViewModel,它看起来像这样......

public class SiteViewModel
{
    public Site Site { get; set; }
    public bool WasPosted { get; set; }
    public IEnumerable<SiteType> AvailableSiteTypes { get; set; }
    public IEnumerable<SiteType> SelectedSiteTypes { get; set; }
}

原因是我想使用 MVC 的 CheckBoxList 扩展,如此处所述

现在,当我创建一个新站点并向其添加 SiteTypes 时,一切正常,但是当我尝试编辑现有记录时,我开始遇到问题。

这是我在控制器中的编辑 GET 方法....

    public ActionResult Edit(int id = 0)
    {
        Site site = _repository.GetSiteByID(id);
        if (site == null)
        {
            return HttpNotFound();
        }

        var model = new SiteViewModel();
        model.AvailableSiteTypes = _repository.GetSiteTypes();
        model.SelectedSiteTypes = site.SiteTypes;
        model.Site = site;

        return View(model);
    }

而 post 方法最初看起来是这样的......

    [HttpPost]
    public ActionResult Edit(SiteViewModel siteViewModel, int[] siteTypes)
    {

        if (ModelState.IsValid)
        {
            _repository.UpdateSite(siteViewModel.Site, siteTypes);
            _repository.Save();
            return RedirectToAction("Index");
        }

        siteViewModel.AvailableSiteTypes = _repository.GetSiteTypes();
        List<SiteType> selectedSiteTypes = _repository.GetSiteTypes(siteTypes).ToList();
        if (selectedSiteTypes.Count > 0)
        {
            siteViewModel.SelectedSiteTypes = selectedSiteTypes;
        }
        return View(siteViewModel);

    }

现在我遇到的问题是 siteViewModel.Site 从表单中正确填充了更新的数据,但是 Id 列被设置为“0”,即使它是现有记录而不是新记录。我已经尝试了一切,但我不知道为什么。我可以让它工作的唯一方法是接受一个“id”参数并手动将它设置为这样的站点对象......

HttpPost]
    public ActionResult Edit(int id, SiteViewModel siteViewModel, int[] siteTypes)
    {
        siteViewModel.Site.Id = id;
        ......

但与其他一切结合在一起的程度相比,它感觉真的很混乱。

这是唯一的方法吗?我错过了什么吗?

非常感谢您花时间阅读我的帖子。对不起,太长了,我不知道该怎么解释...

4

3 回答 3

2

将实际实体发送到您的视图从来都不是一个好主意,您的视图模型应该只获取向用户呈现视图所需的数据。如果您需要将有关每个视图的信息传递Site给视图,则创建一个单独的视图模型或 DTO 并传递它,例如

siteViewModel.Site = new SiteDto()
{
    Id = site.Id,
    Name = site.Name,
    ...
}

实体具有隐藏的属性,用于将其映射回数据库中的记录,当您将实体传递到视图或从视图传递实体时,此信息通常会丢失。正确的方法是向视图发送它需要的所有数据,仅此而已。然后在您的POST方法中,重新拉出您的实体并应用视图模型中的更改。

如果您发现自己到处都在这样做,您可以使用AutoMapper 。

于 2012-09-17T11:53:13.220 回答
0

您可能需要在编辑页面中添加 SiteId,看起来像

@Html.HiddenFor(model => model.Site.Id)

然后整个模型绑定/MVC 框架应该工作并确保 id 被保留。

于 2012-09-17T11:43:57.253 回答
0

遇到同样的问题,最终以 Model 的 ViewModel 引用名称结束,对于您的情况:

[HttpPost]
    public ActionResult Edit(SiteViewModel siteViewModel, int[] siteTypes)
{
...you controller code.
}

将其更改为:

[HttpPost]
    public ActionResult Edit(SiteViewModel model, int[] siteTypes)
{
...you controller code.
}
于 2014-11-27T06:24:43.087 回答