如何不使用表单将视图数据/模型传递至ASP.NET Core控制器Update方法
问题描述
在ASP.NET Core项目中,需要将Index视图中的TblMatHang模型数据传递至HomeController的Update动作方法,以此更新对应商品的信息,修改其属性值并保存后返回视图展示在下方表格中。尝试过嵌套表单和JavaScript,但均未成功或产生诸多问题。
Index.cshtml视图代码
@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers @using Assignment3.Models @model TblMatHang <form id="frm" asp-controller="Home" asp-action="Index" method="post"> Product Code: <select name="maHang" onchange="onChange()"> @foreach (var item in ViewBag.MatHangs) { @if (ViewBag.SelectedID == item.MaHang) { <option value="@item.MaHang" selected>@item.MaHang</option> } else { <option value="@item.MaHang">@item.MaHang</option> } } </select> </form> Product name <form asp-controller="Home" asp-action="FilterName" method="post"> <input type="text" name="Fname" asp-for="Tenhang" /> <button type="submit">Filter by Name</button> </form> Unit <input type="text" asp-for="Dvt" /> <br /> <form asp-controller="Home" asp-action="FilterPrice" method="post"> Old Price <input type="number" name="oldP" asp-for="Gia" /> --> New <input type="number" name="newP" /> <button type="submit">Filter by Price</button> </form> Image link <form asp-controller="Home" asp-action="FilterImage" method="post"> <input type="text" asp-for="Image" name="Image" /> <button type="submit">Filter by Image</button> </form> <table> <tr> <td> <form asp-controller="Home" asp-action="Update" method="post"> <button type="submit">UPDATE</button> </form> </td> <td> <form asp-controller="Home" asp-action="Index"> <button type="submit">RESET</button> </form> </td> </tr> </table> <script> function onChange() { document.getElementById("frm").submit(); } </script> <br /> Danh sach mat hang: <form id="frm" asp-controller="Home" asp-action="Index" method="post"> <table border="1"> <tr> <th>Ma Hang</td> <th>Ten Hang</th> <th>DVT</th> <th>Gia</th> <th>Image</th> </tr> @foreach (var item in ViewBag.MatHangs) { <tr> <td>@item.MaHang</td> <td>@item.Tenhang</td> <td>@item.Dvt</td> <td>@item.Gia</td> <td>@item.Image</td> </tr> } </table> </form>
HomeController代码
using Assignment3.Models; using Microsoft.AspNetCore.Mvc; using System; using System.Linq; namespace Assignment3.Controllers { public class HomeController : Controller { public IActionResult Index() { using (MyOrderContext context = new MyOrderContext()) { var list = context.TblMatHangs.ToList(); ViewBag.MatHangs = context.TblMatHangs.ToList(); return View(); } } [HttpPost] public IActionResult Index(string maHang) { using (MyOrderContext context = new MyOrderContext()) { ViewBag.SelectedID = maHang; ViewBag.MatHangs = context.TblMatHangs.ToList(); TblMatHang m = context.TblMatHangs .SingleOrDefault(x => x.MaHang == maHang); return View(m); } } [HttpPost] public IActionResult FilterName(string fname) { string search = fname; using (MyOrderContext context = new MyOrderContext()) { ViewBag.MatHangs = context.TblMatHangs.ToList(); TblMatHang m = context.TblMatHangs .FirstOrDefault(x => x.Tenhang.ToLower().Contains(search)); ViewBag.MatHangs = context.TblMatHangs .Where(x => x.Tenhang.ToLower().Contains(search)).ToList(); return View("Index", m); } } public IActionResult FilterPrice(float oldP, float newP) { float oldPrice = oldP; float newPrice = newP; using (MyOrderContext context = new MyOrderContext()) { ViewBag.MatHangs = context.TblMatHangs.ToList(); TblMatHang m = context.TblMatHangs .FirstOrDefault(x => x.Gia > oldPrice && x.Gia < newPrice); ViewBag.MatHangs = context.TblMatHangs .Where(x => x.Gia > oldPrice && x.Gia < newPrice).OrderBy(x => x.Gia).ToList(); return View("Index", m); } } [HttpPost] public IActionResult Update(TblMatHang m) { using (MyOrderContext context = new MyOrderContext()) { m = new TblMatHang { }; return View(m); } } [HttpPost] public IActionResult FilterImage(string image) { string search = image; using (MyOrderContext context = new MyOrderContext()) { ViewBag.MatHangs = context.TblMatHangs.ToList(); TblMatHang m = context.TblMatHangs .FirstOrDefault(x => x.Image.ToLower().Contains(search)); ViewBag.MatHangs = context.TblMatHangs .Where(x => x.Image.ToLower().Contains(search)).ToList(); return View("Index", m); } } } }
解决方案
核心问题分析
- Update表单仅含提交按钮,未包含任何模型字段,无法传递修改后的数据
- 多个分散表单导致模型数据无法统一收集
- Update方法内错误重置了传入的模型对象,未执行实际的数据库更新操作
1. 重构Index视图的Update表单
将需要更新的字段和商品标识(隐藏字段)整合到同一个Update表单中,确保提交时传递完整模型数据:
@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers @using Assignment3.Models @model TblMatHang <!-- 商品选择下拉框 --> <form id="frm-select" asp-controller="Home" asp-action="Index" method="post"> Product Code: <select name="maHang" onchange="onChange()"> @foreach (var item in ViewBag.MatHangs) { <option value="@item.MaHang" @(ViewBag.SelectedID == item.MaHang ? "selected" : "")>@item.MaHang</option> } </select> </form> <!-- 统一更新表单 --> <form asp-controller="Home" asp-action="Update" method="post"> <!-- 隐藏字段传递商品编码,用于定位数据库记录 --> <input type="hidden" asp-for="MaHang" /> Product name: <input type="text" asp-for="Tenhang" /> <br/> Unit: <input type="text" asp-for="Dvt" /> <br/> Price: <input type="number" asp-for="Gia" /> <br/> Image link: <input type="text" asp-for="Image" /> <br/> <button type="submit">UPDATE</button> <button type="submit" formaction="@Url.Action("Index")" formmethod="get">RESET</button> </form> <!-- 筛选功能保留,优化表单结构 --> <form asp-controller="Home" asp-action="FilterName" method="post"> Filter by Name: <input type="text" name="Fname" /> <button type="submit">Filter</button> </form> <form asp-controller="Home" asp-action="FilterPrice" method="post"> Filter by Price: <input type="number" name="oldP" /> --> <input type="number" name="newP" /> <button type="submit">Filter</button> </form> <form asp-controller="Home" asp-action="FilterImage" method="post"> Filter by Image: <input type="text" name="Image" /> <button type="submit">Filter</button> </form> <br/> Danh sach mat hang: <table border="1"> <tr> <th>Ma Hang</th> <th>Ten Hang</th> <th>DVT</th> <th>Gia</th> <th>Image</th> </tr> @foreach (var item in ViewBag.MatHangs) { <tr> <td>@item.MaHang</td> <td>@item.Tenhang</td> <td>@item.Dvt</td> <td>@item.Gia</td> <td>@item.Image</td> </tr> } </table> <script> function onChange() { document.getElementById("frm-select").submit(); } </script>
2. 修改HomeController的Update方法
实现实际的数据库更新逻辑,保存后返回最新的商品列表:
using Assignment3.Models; using Microsoft.AspNetCore.Mvc; using System.Linq; namespace Assignment3.Controllers { public class HomeController : Controller { // 保留原有方法,仅修改Update方法 [HttpPost] public IActionResult Update(TblMatHang updatedMatHang) { using (MyOrderContext context = new MyOrderContext()) { // 根据商品编码获取数据库中的原有记录 var existingItem = context.TblMatHangs .SingleOrDefault(x => x.MaHang == updatedMatHang.MaHang); if (existingItem != null) { // 更新属性值 existingItem.Tenhang = updatedMatHang.Tenhang; existingItem.Dvt = updatedMatHang.Dvt; existingItem.Gia = updatedMatHang.Gia; existingItem.Image = updatedMatHang.Image; // 保存到数据库 context.SaveChanges(); } // 更新商品列表,确保视图展示最新数据 ViewBag.MatHangs = context.TblMatHangs.ToList(); return View("Index", updatedMatHang); } } // 补充FilterPrice方法的HttpPost特性(原代码遗漏) [HttpPost] public IActionResult FilterPrice(float oldP, float newP) { using (MyOrderContext context = new MyOrderContext()) { var filteredList = context.TblMatHangs .Where(x => x.Gia > oldP && x.Gia < newP).OrderBy(x => x.Gia).ToList(); ViewBag.MatHangs = filteredList; var model = filteredList.FirstOrDefault(); return View("Index", model); } } // 其他原有方法保持不变... public IActionResult Index() { using (MyOrderContext context = new MyOrderContext()) { ViewBag.MatHangs = context.TblMatHangs.ToList(); return View(); } } [HttpPost] public IActionResult Index(string maHang) { using (MyOrderContext context = new MyOrderContext()) { ViewBag.SelectedID = maHang; ViewBag.MatHangs = context.TblMatHangs.ToList(); TblMatHang m = context.TblMatHangs .SingleOrDefault(x => x.MaHang == maHang); return View(m); } } [HttpPost] public IActionResult FilterName(string fname) { string search = fname?.ToLower() ?? string.Empty; using (MyOrderContext context = new MyOrderContext()) { var filteredList = context.TblMatHangs .Where(x => x.Tenhang.ToLower().Contains(search)).ToList(); ViewBag.MatHangs = filteredList; var model = filteredList.FirstOrDefault(); return View("Index", model); } } [HttpPost] public IActionResult FilterImage(string image) { string search = image?.ToLower() ?? string.Empty; using (MyOrderContext context = new MyOrderContext()) { var filteredList = context.TblMatHangs .Where(x => x.Image.ToLower().Contains(search)).ToList(); ViewBag.MatHangs = filteredList; var model = filteredList.FirstOrDefault(); return View("Index", model); } } } }
3. 额外优化点
- 移除重复的
id="frm"表单,避免DOM元素ID冲突 - 给FilterPrice方法补充
[HttpPost]特性,修复无法接收POST请求的问题 - 优化筛选方法的空值处理,避免空引用异常
- 将RESET按钮整合到Update表单中,减少独立表单数量
内容的提问来源于stack exchange,提问作者Harry Vo
相关产品推荐
相关产品推荐

