ASP.NET Core Razor MVC:点击按钮提交模型对象至控制器异常问题
问题原因
你遇到的问题是因为ASP.NET Core的GET请求模型绑定无法直接解析URL中的复杂对象。当你通过<a>标签的URL传递item = item时,路由系统只能识别简单类型(比如int、string)的参数,无法将URL中的参数映射到PharmacyItem类的属性上,所以控制器会创建一个默认构造的空对象。
解决方案
推荐两种处理方式,优先选第一种:
方案1:仅传递商品ID(推荐)
不需要传递整个商品对象,只传商品的唯一标识ItemId,控制器通过ID从数据源获取完整商品信息,这种方式更安全、简洁,也符合RESTful设计。
修改视图代码
把链接中的item = item替换为itemId = item.ItemId:
@model IEnumerable<Razor.Pharmacy.Domain.Entities.PharmacyItem> <div class="container"> <div class="row"> @foreach (var item in Model) { <!-- 其他商品卡片代码 --> <a href="@Url.Action("AddToBasket", "Basket", new { customerId = 0, itemId = item.ItemId })" class="btn btn-dark">Add To Basket</a> <!-- 其他商品卡片代码 --> } </div> </div>
修改控制器代码
注入获取商品的服务(比如IPharmacyItemService),通过ID获取商品后再调用购物车服务:
// BasketController.cs private readonly IBasketService _basketService; private readonly IPharmacyItemService _pharmacyItemService; // 构造函数注入服务 public BasketController(IBasketService basketService, IPharmacyItemService pharmacyItemService) { _basketService = basketService; _pharmacyItemService = pharmacyItemService; } public IActionResult AddToBasket(int customerId, int itemId) { // 通过ID获取完整商品对象 var pharmacyItem = _pharmacyItemService.GetItemById(itemId); if (pharmacyItem != null) { _basketService.AddItemToBasket(customerId, pharmacyItem); } // 重定向回商品列表或购物车页面 return RedirectToAction("Index"); }
方案2:用POST请求传递完整对象(不推荐)
如果必须传递完整商品对象,可以用表单+POST请求,通过隐藏字段存储商品的所有属性,让模型绑定能正确解析:
修改视图代码
把<a>标签替换为表单,添加对应商品属性的隐藏字段:
@model IEnumerable<Razor.Pharmacy.Domain.Entities.PharmacyItem> <div class="container"> <div class="row"> @foreach (var item in Model) { <!-- 其他商品卡片代码 --> <form asp-action="AddToBasket" asp-controller="Basket" method="post"> <input type="hidden" name="customerId" value="0" /> <input type="hidden" name="item.ItemId" value="@item.ItemId" /> <input type="hidden" name="item.Name" value="@item.Name" /> <input type="hidden" name="item.Price" value="@item.Price" /> <input type="hidden" name="item.Quantity" value="@item.Quantity" /> <input type="hidden" name="item.RequiresPrescription" value="@item.RequiresPrescription" /> <button type="submit" class="btn btn-dark">Add To Basket</button> </form> <!-- 其他商品卡片代码 --> } </div> </div>
修改控制器代码
给方法添加[HttpPost]特性,确保接收POST请求:
// BasketController.cs [HttpPost] public IActionResult AddToBasket(int customerId, PharmacyItem item) { _basketService.AddItemToBasket(customerId, item); return RedirectToAction("Index"); }
关键说明
- GET请求的URL只能传递简单类型参数,无法直接绑定复杂对象,这是ASP.NET Core模型绑定的规则。
- 方案1更安全,避免在URL中暴露商品的价格、名称等敏感信息,也不会出现URL过长的问题。
内容的提问来源于stack exchange,提问作者tenticon
相关产品推荐
相关产品推荐

