ASP.NET MVC中绑定Book模型List类型BookComment属性的asp-for写法问题
解决方案
核心原因是你当前视图的强类型模型是Book类,其中BookComment是集合类型,自然不能直接绑定集合下的单个对象属性。而且你的POST接口本身就是接收单个BookComment对象,不需要绑定Book类下的评论集合,有两种实现方案可选:
方案1:直接匹配属性名(最简单,无需改现有模型结构)
第一步:修正视图表单代码
你之前的form标签提前闭合,所有输入控件都不在表单范围内,首先要把所有表单项包裹在form标签内,同时新增隐藏域传递当前图书ID,每个表单控件的name属性和BookComment的属性名保持一致即可:
@model LibraryNew.Models.Book <h5 class="mt-4">添加评论</h5> <p>您的邮箱不会公开</p> <form asp-action="Book" method="post"> <!-- 隐藏域传递当前图书ID,绑定到提交的BookComment的BookID字段 --> <input type="hidden" name="BookID" value="@Model.BookID" /> <div class="my-3"> <div class="form-group"> <label>评分:</label> <select name="Stars" class="form-control col-md-1"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> </div> </div> <div class="form-group"> <label>昵称</label> <input name="Name" type="text" class="form-control" placeholder="请输入您的昵称"> </div> <div class="form-group"> <label>邮箱</label> <input name="Email" type="email" class="form-control" placeholder="name@example.com"> </div> <div class="form-group"> <label>评论内容</label> <textarea name="Review" class="form-control" rows="3"></textarea> </div> <button type="submit" class="btn btn-primary mt-3">提交评论</button> </form>
第二步:修正控制器POST动作
你之前的跳转没有传图书ID,会导致提交后页面报错,同时可以自动补全评论提交时间,无需用户填写:
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Book(BookComment comment) { // 自动补全评论提交时间 comment.Date = DateTime.Now; _db.bookComments.Add(comment); _db.SaveChanges(); // 跳转回当前图书详情页,传递图书ID return RedirectToAction("Book", new { id = comment.BookID }); }
方案2:使用视图模型(更规范,支持强类型绑定)
如果想要用asp-for强类型绑定避免拼写错误,可以新增一个视图模型承载页面所需的所有数据:
第一步:新增视图模型
public class BookDetailViewModel { // 存储当前图书信息 public Book CurrentBook { get; set; } // 存储用户提交的新评论 public BookComment NewComment { get; set; } = new BookComment(); }
第二步:修改控制器GET动作
public IActionResult Book(int? id) { var book = _db.Books.Include(o => o.BookComment).FirstOrDefault(p => p.BookID == id); var viewModel = new BookDetailViewModel { CurrentBook = book, NewComment = new BookComment { BookID = book.BookID } }; return View(viewModel); }
第三步:修改视图代码,支持强类型绑定
@model LibraryNew.Models.BookDetailViewModel <h5 class="mt-4">添加评论</h5> <p>您的邮箱不会公开</p> <form asp-action="Book" method="post"> <div class="my-3"> <div class="form-group"> <label>评分:</label> <!-- 直接强类型绑定新评论的属性 --> <select asp-for="NewComment.Stars" class="form-control col-md-1"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> </div> </div> <div class="form-group"> <label>昵称</label> <input asp-for="NewComment.Name" type="text" class="form-control" placeholder="请输入您的昵称"> </div> <div class="form-group"> <label>邮箱</label> <input asp-for="NewComment.Email" type="email" class="form-control" placeholder="name@example.com"> </div> <div class="form-group"> <label>评论内容</label> <textarea asp-for="NewComment.Review" class="form-control" rows="3"></textarea> </div> <input type="hidden" asp-for="NewComment.BookID" /> <button type="submit" class="btn btn-primary mt-3">提交评论</button> </form>
第四步:修改POST动作参数接收规则
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Book(BookDetailViewModel viewModel) { var comment = viewModel.NewComment; comment.Date = DateTime.Now; _db.bookComments.Add(comment); _db.SaveChanges(); return RedirectToAction("Book", new { id = comment.BookID }); }
其他注意点
- 原表单中5星选项的value错误写为1,需要修正为5
- 展示已有评论时,遍历
Model.BookComment(方案1)或者Model.CurrentBook.BookComment(方案2)即可
内容的提问来源于stack exchange,提问作者matteo0402
相关产品推荐
相关产品推荐

