ASP.NET Core中如何从视图向Get Action传递超3000条记录的List模型?
解决ASP.NET Core中通过标签传递大量Product列表到Get Action的问题
问题分析
你遇到的核心问题有两个:
- Get请求无法直接传递复杂模型:URL长度有限,且带外键关联的
List<Product>无法被框架自动序列化为路由参数,直接通过asp-route-model或Url.Action传递@Model必然失败。 - TempData序列化异常:EF查询返回的
Product是代理对象(带跟踪状态),无法直接被默认的TempData序列化机制处理,导致500错误。
以下是几种可行的解决方案,按推荐程度排序:
方案一:传递筛选条件而非完整模型(推荐)
直接传递大量数据到Get Action既不安全也不高效,最优方式是把生成产品列表的筛选参数传递给PrintProducts,在该Action中重新查询数据。
修改PrintProducts Action
public IActionResult PrintProducts(int side, MyViewModel myViewModel) { List<Product> products; if (side == 0) { products = ShowAllProducts(); } else { products = FilterProducts(myViewModel); } return View(products); }
修改视图中的标签
传递筛选所需的参数(从ViewBag或页面上下文获取):
@model IEnumerable<Product> <a title="Print" asp-action="PrintProducts" asp-route-side="@ViewBag.side" asp-route-categoryId="@ViewData["CategoryId"]" asp-route-priceRange="@ViewData["PriceRange"]"> 打印 </a>
如果MyViewModel参数较多,可拆分为单个路由参数传递,再在PrintProducts中重新构建MyViewModel执行筛选。
方案二:序列化模型后存入TempData(适合小量数据)
若必须传递完整模型,需先将Product列表序列化为可存储的格式(如JSON),同时避免EF代理对象的序列化问题。
步骤1:安装Newtonsoft.Json包
通过NuGet安装Newtonsoft.Json,用于处理复杂对象的序列化。
步骤2:修改第一个Action
using Newtonsoft.Json; public IActionResult ShowProducts(int side, MyViewModel myViewModel) { ViewBag.side = side; List<Product> products; if (side == 0) { // 关闭跟踪避免代理对象,或用ProjectTo映射为DTO products = ShowAllProducts().AsNoTracking().ToList(); } else { products = FilterProducts(myViewModel).AsNoTracking().ToList(); } // 序列化并存储到TempData,处理循环引用 TempData["MyModel"] = JsonConvert.SerializeObject(products, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); return View(products); }
步骤3:修改PrintProducts Action
using Newtonsoft.Json; public IActionResult PrintProducts() { if (TempData["MyModel"] is string json) { var model = JsonConvert.DeserializeObject<List<Product>>(json); return View(model); } // 处理数据不存在的情况 return RedirectToAction("ShowProducts"); }
⚠️ 注意:此方法不适合超大量数据,TempData依赖Session存储,有大小限制。
方案三:改用POST请求传递模型(适合必须传完整数据的场景)
Get请求不适合传递大量数据,可将标签改为表单提交,用POST方式传递模型。
视图代码
@model IEnumerable<Product> <form asp-action="PrintProducts" method="post"> @{ int i = 0; } @foreach (var product in Model) { <input type="hidden" name="model[@i].Id" value="@product.Id" /> <input type="hidden" name="model[@i].Name" value="@product.Name" /> <!-- 依次添加Product的其他属性隐藏字段 --> i++; } <button type="submit" title="Print">打印</button> </form>
修改PrintProducts Action
[HttpPost] public IActionResult PrintProducts(List<Product> model) { return View(model); }
⚠️ 注意:大量产品会生成过多隐藏字段,导致请求体过大,维护成本高。
内容的提问来源于stack exchange,提问作者NedaM
相关产品推荐
相关产品推荐

