我希望你能帮助我,我对MVC和实体框架都很陌生,并试图解决它。我正在使用MVC4和EF5。
以下是我要做的事情的概述......
我有两个实体,Site和SiteType。每个站点可以有多个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扩展,如here所述
现在一切都在我创建新网站并向其添加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”参数并手动将它设置为Site对象,就像这样......
HttpPost]
public ActionResult Edit(int id, SiteViewModel siteViewModel, int[] siteTypes)
{
siteViewModel.Site.Id = id;
......
但与其他一切联系在一起的情况相比,它感觉非常混乱。
这是唯一的方法吗?我错过了什么吗?
非常感谢您花时间阅读我的帖子。对不起,它太长了,我不知道怎么解释它......
答案 0 :(得分:2)
将实际实体发送到您的视图绝不是一个好主意,您的视图模型应该只获取向用户呈现视图所需的数据。如果您需要将有关每个Site
的信息传递给视图,则创建一个单独的视图模型或DTO,然后传递它,例如。
siteViewModel.Site = new SiteDto()
{
Id = site.Id,
Name = site.Name,
...
}
实体具有隐藏的属性,用于将其映射回数据库中的记录,当您将实体传入/从视图传递时,此信息通常会丢失。正确的方法是向视图发送所需的所有数据,而不是更多。然后在您的POST
方法中,重新拉取您的实体并应用视图模型中的更改。
如果您发现自己在整个地方都这样做,可以使用AutoMapper。
答案 1 :(得分:1)
遇到同样的问题,最终将ViewModel referance名称改为Model,对于您的情况:
[HttpPost]
public ActionResult Edit(SiteViewModel siteViewModel, int[] siteTypes)
{
...you controller code.
}
将其更改为:
[HttpPost]
public ActionResult Edit(SiteViewModel model, int[] siteTypes)
{
...you controller code.
}
答案 2 :(得分:0)
您可能需要在编辑页面中添加SiteId,看起来像
@Html.HiddenFor(model => model.Site.Id)
然后整个模型绑定/ MVC框架应该工作并确保保留id。