ASP.NET MVC采购发票创建页:实时展示同票商品列表问题求助
问题:采购发票页面实时展示已添加商品的实现问题
我需要在创建供应商采购发票的同一页面中,实时列出该发票下已添加的商品。每添加一个商品后,它需立即显示在列表中。尝试用Partial View实现但没成功,相关代码如下:
控制器代码
[Area("***")] public class PurchaseController : Controller { private readonly IUnitOfWork _unitOfWork; public PurchaseController(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public IActionResult Index() { IEnumerable<Purchases> objPurchaseList = _unitOfWork.Purchase.GetAll(includeProperties:"Suppliers").ToList(); return View(objPurchaseList); } public IActionResult _CreatePartialView(string? invoice) { PurchaseVM purchaseVM = new() { purchases = new(), }; if (invoice==null) { return RedirectToAction(nameof(Create)); } List<Purchases> purchaseList = _unitOfWork.Purchase.GetAll().Where(u => u.PurchaseInvoice == invoice).ToList(); return RedirectToAction(nameof(Create)); } //GET public IActionResult Create() { PurchaseVM purchaseVM = new() { purchases = new(), GroupList = _unitOfWork.Group.GetAll().Select(u => new SelectListItem { Text = u.GroupName, Value = u.GroupId.ToString() }), SupplierList = _unitOfWork.Supplier.GetAll().Select(u => new SelectListItem { Text = u.SupplierName, Value = u.SupplierId.ToString() }), ProductList = _unitOfWork.Product.GetAll().Select(u => new SelectListItem { Text = u.ProductName, Value = u.ProductId.ToString() }), }; return View(purchaseVM); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult Create(Purchases obj) { if(ModelState.IsValid) { _unitOfWork.Purchase.Add(obj); _unitOfWork.Save(); TempData["success"]= "Product added successfully."; return View(obj); } return View(); } }
局部视图代码
@model IEnumerable<Purchases> @foreach (var obj in Model.GroupBy(u => u.PurchaseInvoice)) { <tr> <td width="15%"> @obj.First().PurcahseDate </td> <td width="15%"> @obj.First().PurchaseInvoice </td> <td width="35%"> @obj.First().Suppliers.SupplierName </td> <td width="15%" style="text-align:right"> @obj.Sum(u => u.PurchaseTotal) </td> <td width="20%"> <div class="w-75 btn-group" role="group"> <a asp-controller="Purchase" asp-action="Edit" style="width:120px" asp-route-id="@obj.First().PurchaseInvoice" class="btn btn-primary mx-2"> <i class="bi bi-pencil-square"></i> Edit</a> <a asp-controller="Purchase" asp-action="Delete" style="width:125px" asp-route-id="@obj.First().PurchaseInvoice" class="btn btn-danger mx-2"> <i class="bi bi-trash-fill"></i> Delete</a> </div> </td> </tr> }
视图模型代码
namespace SysComm.Models.ViewModels { public class PurchaseVM { public Purchases purchases { get;set; } public List<Purchases> purchaseList { get; set; } [ValidateNever] public IEnumerable<SelectListItem> GroupList { get; set; } [ValidateNever] public IEnumerable<SelectListItem> SupplierList { get; set; } [ValidateNever] public IEnumerable<SelectListItem> ProductList { get; set; } } }
主视图片段代码
</div> <table class="table table-bordered table-striped" style="width:100%"> <thead> <tr> <th> Id </th> <th> Date </th> <th> Customer Name </th> <th> Customer Phone </th> <th> Action </th> </tr> </thead> <tbody> <partial name="~/Areas/Admin/Views/Purchase/_CreatePartialView.cshtml" /> </tbody> </table> </div> </div> </div>
问题分析
当前代码的核心问题:
_CreatePartialView方法未正确返回局部视图,而是重定向到Create页面,无法渲染商品列表- 主视图调用局部视图时未传递当前发票的商品数据
- HttpPost的Create方法返回单个Purchases对象,未携带当前发票的商品列表,无法更新视图
修正方案
1. 修复_CreatePartialView方法
让它返回局部视图并传递对应发票的商品列表:
public IActionResult _CreatePartialView(string invoice) { if (string.IsNullOrEmpty(invoice)) { return PartialView(new List<Purchases>()); } var purchaseList = _unitOfWork.Purchase.GetAll(u => u.PurchaseInvoice == invoice).ToList(); return PartialView(purchaseList); }
2. 调整HttpPost的Create方法
添加商品后,重新构建视图模型并携带当前发票的商品列表:
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Create(Purchases obj) { if(ModelState.IsValid) { _unitOfWork.Purchase.Add(obj); _unitOfWork.Save(); TempData["success"]= "Product added successfully."; // 重新构建视图模型,包含当前发票的商品列表 var purchaseVM = new PurchaseVM { purchases = new Purchases { PurchaseInvoice = obj.PurchaseInvoice }, purchaseList = _unitOfWork.Purchase.GetAll(u => u.PurchaseInvoice == obj.PurchaseInvoice).ToList(), GroupList = _unitOfWork.Group.GetAll().Select(u => new SelectListItem { Text = u.GroupName, Value = u.GroupId.ToString() }), SupplierList = _unitOfWork.Supplier.GetAll().Select(u => new SelectListItem { Text = u.SupplierName, Value = u.SupplierId.ToString() }), ProductList = _unitOfWork.Product.GetAll().Select(u => new SelectListItem { Text = u.ProductName, Value = u.ProductId.ToString() }) }; return View(purchaseVM); } // 验证失败时重新加载下拉列表 var errorVM = new PurchaseVM { purchases = obj, GroupList = _unitOfWork.Group.GetAll().Select(u => new SelectListItem { Text = u.GroupName, Value = u.GroupId.ToString() }), SupplierList = _unitOfWork.Supplier.GetAll().Select(u => new SelectListItem { Text = u.SupplierName, Value = u.SupplierId.ToString() }), ProductList = _unitOfWork.Product.GetAll().Select(u => new SelectListItem { Text = u.ProductName, Value = u.ProductId.ToString() }) }; return View(errorVM); }
3. 修正主视图的局部视图调用
传递当前视图模型中的商品列表:
<tbody> @await Html.PartialAsync("~/Areas/Admin/Views/Purchase/_CreatePartialView.cshtml", Model.purchaseList) </tbody>
4. 修复局部视图拼写错误
把PurcahseDate改为PurchaseDate:
<td width="15%"> @obj.First().PurchaseDate </td>
可选:实现无刷新实时更新
如果需要避免页面刷新,用AJAX提交表单并刷新局部视图:
在主视图添加脚本:
<script> $('form').submit(function(e) { e.preventDefault(); var formData = $(this).serialize(); var invoiceNumber = $('#PurchaseInvoice').val(); $.ajax({ url: $(this).attr('action'), type: 'POST', data: formData, success: function() { // 刷新商品列表 $('#purchaseItemsTbody').load('@Url.Action("_CreatePartialView", "Purchase")?invoice=' + invoiceNumber); // 清空表单 $('form')[0].reset(); $('#successMsg').text('商品添加成功'); }, error: function() { $('#errorMsg').text('商品添加失败'); } }); }); </script>
同时给表格tbody添加ID:
<tbody id="purchaseItemsTbody"> @await Html.PartialAsync("~/Areas/Admin/Views/Purchase/_CreatePartialView.cshtml", Model.purchaseList) </tbody>
内容的提问来源于stack exchange,提问作者Pe Zar
相关产品推荐
相关产品推荐

