You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:19:22