提问人:NedaM 提问时间:10/26/2023 最后编辑:NedaM 更新时间:10/27/2023 访问量:90
如何在 ASP.Net Core 中将模型(包含超过 3000 条记录的列表)从一个视图发送到另一个 get 操作?
How to send a model (a List with more than 3000 records) from a view to another get action in ASP.Net Core?
问:
我有一个 ASP.net 核心项目。我想通过“a”标签将整个模型(即产品列表)从视图发送到控制器中的另一个获取操作。我使用了 TempData,但它不起作用。产品模型具有许多属性和外键。 下面是一个示例:
第一个动作是:
public IActionResult ShowProducts(int side, MyViewModel myViewModel)
{
ViewBag.side = side;
if (side == 0)
{
List<Product> products = ShowAllProducts();
return View(products);
}
List<Product> products2 = FilterProducts(myViewModel);
return View(products2 );
}
List<Product> FilterProducts(MyViewModel myViewModel)
{
List<Product> Products = new List<Product>() {};
//some code...
return products;
}
List<Product> ShowAllProducts()
{
return _context.Products.Include(p => p.Table1).Include(p => p.Table2)
.Include(p => p.Table3).Include(p => p.Table4)
.Include(p => p.Table5).Include(p => p.Table6)
.Include(p => p.Table7).Include(p => p.Table8).Tolist();
}
第二个动作是:
public IActionResult PrintProducts(List<Product> model)
{
return View(model);
}
ShowProducts 视图是:
@model IEnumerable<Product>
@*some tag*@
<a title="Print" asp-action="PrintProducts" asp-route-model ="@Model"></a>
@*some tag*@
在此示例中,第二个操作中的模型为空。实际上它不发送。
我这样更改了视图:
@model IEnumerable<Product>
@*some tag*@
<a title="Print" href="@Url.Action("PrintProducts", "Controller", new { model = @Model })"></a>
@*some tag*@
但这种方式也行不通。
我使用并更改了这样的操作:
第一个动作:TempData
public IActionResult ShowProducts(int side, MyViewModel myViewModel)
{
ViewBag.side = side;
if (side == 0)
{
List<Product> products = ShowAllProducts();
TempData["MyModel"] = products;
return View(products);
}
List<Product> products2 = FilterProducts(myViewModel);
TempData["MyModel"] = products2;
return View(products2 );
}
第二个动作是:
public IActionResult PrintProducts()
{
List<Product> model= TempData["MyModel"] as List<Product>;
return View(model);
}
但这样一来,第一个视图根本没有加载!我的状态代码为 500。
有什么方法可以解决这个问题吗?
答:
分页
通常,如果要显示大量数据,则可以使用分页。这实质上是将数据划分为多个称为页面的记录块。现在,如果你想在一个页面上显示所有数据,你可以在水下多次调用GET来获取你想要的所有数据。这样可以减少单个调用中的数据量。它还使事情更具可扩展性。
滤波
使用筛选,因此用户可以根据某些条件进行筛选。例如,搜索框。这将允许用户输入名称,并且您仅返回符合这些条件的项目。
订购
如果要对数据进行分页,还需要确保按特定顺序获取数据。如果每次调用的数据都是随机顺序的,则每次提取页面时,页面将包含不同的项目。它还允许用户按不同的属性进行排序。
例
这是我如何做到这一点的,它还包含过滤和排序。
[HttpGet]
[Route("GetAll")]
virtual public async Task<ActionResult<DbItem[]>> GetAll(string? filter, string? order, int? pageNo, int? pageSize)
{
IQueryable<DbItem> query = _context.Set<DbItem>();
// Apply filters to the query (you need to implement your filter logic)
if (!string.IsNullOrEmpty(filter))
{
//Example of how to filter by title
query = query.Where(a=>a.Title.Contains(filter));
}
// Apply ordering to the query if orderBy is provided
if (!string.IsNullOrEmpty(order))
{
// Exmaple where order contains your property name
query.OrderBy(e => EF.Property<DbItem>(e, order));
}
// Ensure the pagesize is something reasonable
pageSize ??= 30;
if (pageSize < 1 || pageSize > 30)
pageSize = 30;
// Ensure the page is something reasonable
pageNo ??= 0;
if (pageNo < 0)
pageNo = 0;
// Apply paging to the query
int skip = pageNo.Value * pageSize.Value;
query = query.Skip(skip).Take(pageSize.Value);
// Execute the query and return the items
var result = await query.ToListAsync();
return Ok(result);
}
如何显示这一点
在 HTML 方面,根据您想要的用户体验,有不同的解决方案。您在互联网上经常看到的一些选项:
- 在页面底部添加分页器:https://getbootstrap.com/docs/4.0/components/pagination/
- 使用无尽的滚动条,这就是 Instagram、TikTok 等应用程序。
- 使用一个表,当您滚动到底部时,该表会获取新数据。
- 由于您使用的是 ASP 作为前端,因此您可能希望使用 AJAX 获取更多数据,并使用 jQuery 将其附加到页面中。
更多信息
Microsoft文档有一个很好的解释:https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-7.0
评论
默认情况下,tempdata 的提供程序是基于 cookie 的。大多数 Web 客户端(如 Web 浏览器)对每个 Cookie 的最大大小和 Cookie 总数实施限制。使用 Cookie TempData 提供程序时,请验证应用不会超过这些限制。考虑数据的总大小。考虑由于加密和分块而导致的 Cookie 大小增加。
因此,我们不建议您在临时数据中存储 3000 条记录,一种可能的方法是存储记录 ID,然后在另一种方法中使用该 ID 查询数据。
另一种方法是将数据存储在会话、内存缓存或 redis 缓存中。
有关 tempdata 工作原理和选择要存储缓存的存储的更多详细信息,您可以参考本文。
评论