【发布时间】:2015-12-01 19:35:07
【问题描述】:
使用具有多对多关系的实体框架,我很困惑如何从绑定模型的 ASP.NET MVC 控制器更新该关系。
例如一个博客:帖子有很多标签,标签有很多帖子。
帖子控制器编辑操作无法延迟加载 tags 实体:
public class PostsController : Controller
{
[Route("posts/edit/{id}")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Id,Title,Tags")] Post post)
{
// Post tags is null
Post.tags.ToList();
}
}
上面,HTTP Post 将属性绑定到模型;但是,Post.tags 关系为空。
我无法查询.Include(p => p.Tags) 或Attach() 使用此[Bind()] 检索相关标签实体的帖子。
在视图方面,我正在使用标记器并传递表单数据 - 我没有使用 MVC 列表组件。因此,问题不在于绑定视图表单数据 - 问题在于 .tags 属性不是延迟加载实体。
这种关系是有效的——从 Razor cshtml 视图中,我能够遍历集合并查看子标签。
从帖子视图中,我可以查看标签(这有效)
@foreach (var tag in Model.Tags) {
}
从标签视图中,我可以查看帖子(这可行)
@foreach (var post in Model.Posts) {
}
同样,在从 Posts 控制器创建操作时,我可以创建新的标签实体并保持它们的关系。
public class PostsController : Controller
{
[Route("posts/create")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Title,Content")] Post post)
{
string[] tagNames = this.Request.Form["TagNames"].Split(',').Select(tag => tag.Trim()).ToArray();
post.Tags = new HashSet<Tag>();
Tag tag = new Tag();
post.Tags.Add(tag);
if (ModelState.IsValid)
{
db.posts.Add(post);
await db.SaveChangesAsync();
return RedirectToAction("Admin");
}
return View(post);
}
这些关系在任何地方都有效,除了这个编辑 HTTP Post。作为参考,它们被定义为:
public class Post
{
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public virtual ICollection<Post> Posts { get; set; }
}
只有在编辑操作的 HTTP Post 上我不能访问帖子的标签。
如何加载相关标签来更改该集合?
【问题讨论】:
-
当您在表单中POST a collection 时,您需要使用
for循环而不是foreach来获取绑定以识别模型属性。 -
如果
tags在POST方法中为null,那是因为你查看的不正确。显示它。
标签: asp.net asp.net-mvc entity-framework