MVC5:如何通过ViewModel将子实体传递至Create(POST方法)
当然可以用ViewModel创建子实体!
这完全是可行的,而且是这类场景下的常规做法。结合你的Customer实体和评论子实体的需求,我给你梳理下具体实现思路:
1. 先定义评论子实体(Comment)
首先你需要明确Comment实体的结构,它要通过外键关联到Customer:
public class Comment { [Key] public int Id { get; set; } [Required] public string Content { get; set; } // 外键关联Customer的Code字段 public int CustomerCode { get; set; } // 导航属性(可选,方便EF Core关联查询) public Customer Customer { get; set; } }
2. 创建对应的评论ViewModel
ViewModel要封装视图需要展示和提交的数据,这里我们只需要评论内容和关联的Customer编码(可以不用让用户输入,从页面上下文自动获取):
public class CreateCommentViewModel { [Required(ErrorMessage = "请输入评论内容")] [Display(Name = "评论")] public string Content { get; set; } // 这个字段用来存储关联的Customer编码,视图里可以用隐藏域传递 public int CustomerCode { get; set; } }
3. 在概览页面的视图中集成评论表单
在Customer的概览页面里,添加一个基于ViewModel的表单,用来提交评论:
@model YourNamespace.Models.Customer @* 先展示Customer的概览信息 *@ <h3>客户概览</h3> <p>客户编码:@Model.Code</p> <!-- 其他客户信息展示 --> @* 评论提交表单 *@ <h4>添加评论</h4> <form asp-action="AddComment" method="post"> @* 隐藏域传递CustomerCode,不用用户输入 *@ <input type="hidden" asp-for="@Model.Code" name="CustomerCode" /> <div class="form-group"> <label asp-for="Content" class="control-label"></label> <textarea asp-for="Content" class="form-control"></textarea> <span asp-validation-for="Content" class="text-danger"></span> </div> <button type="submit" class="btn btn-primary">提交评论</button> </form>
4. 在控制器中处理评论提交
编写控制器方法接收ViewModel,映射为Comment实体并保存:
public class CustomerController : Controller { private readonly YourDbContext _context; public CustomerController(YourDbContext context) { _context = context; } // 展示Customer概览页面 public async Task<IActionResult> Overview(int code) { var customer = await _context.Customers.FindAsync(code); if (customer == null) { return NotFound(); } return View(customer); } // 处理评论提交 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> AddComment(CreateCommentViewModel model) { if (ModelState.IsValid) { // 验证关联的Customer是否存在(可选但推荐) var customerExists = await _context.Customers.AnyAsync(c => c.Code == model.CustomerCode); if (!customerExists) { ModelState.AddModelError("", "关联的客户不存在"); return RedirectToAction("Overview", new { code = model.CustomerCode }); } // 将ViewModel映射为Comment实体 var comment = new Comment { Content = model.Content, CustomerCode = model.CustomerCode }; _context.Comments.Add(comment); await _context.SaveChangesAsync(); // 提交后返回概览页面 return RedirectToAction("Overview", new { code = model.CustomerCode }); } // 验证失败的话,返回概览页面并显示错误 var customer = await _context.Customers.FindAsync(model.CustomerCode); return View("Overview", customer); } }
一些额外的小提示
- 自动填充外键:尽量不要让用户手动输入CustomerCode,通过路由参数、隐藏域或者会话上下文自动获取,避免输入错误。
- 验证逻辑:除了ViewModel的数据验证,还要确保关联的Customer确实存在,避免无效的外键数据。
- 导航属性:如果需要在概览页面展示该客户的所有评论,可以在Customer实体里添加
public ICollection<Comment> Comments { get; set; } = new List<Comment>();,然后查询Customer时用Include(c => c.Comments)加载关联数据。
内容的提问来源于stack exchange,提问作者Shintaro
相关产品推荐
相关产品推荐

