.NET 6+项目使用WebGrid遭遇IHtmlString未找到错误求助
问题原因
WebGrid和Microsoft.AspNet.WebPages这类组件是.NET Framework时代的产物,依赖仅存在于旧框架中的System.Web.dll(包含IHtmlString),而ASP.NET Core完全重构了底层架构,移除了System.Web相关依赖,因此这些旧组件无法在.NET 6环境中正常工作,必须更换兼容方案。
解决方案
方案一:原生实现分页+排序(无第三方依赖)
适合轻量需求,直接通过ASP.NET Core最小API+前端代码实现。
卸载旧NuGet包
移除所有与Microsoft.AspNet.WebPages相关的包,避免版本冲突。定义数据模型与分页参数
在Program.cs中添加基础模型类:public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } public class PaginationParams { public int PageIndex { get; set; } = 1; public int PageSize { get; set; } = 10; public string SortBy { get; set; } = "Id"; public bool IsAscending { get; set; } = true; }实现后端分页排序逻辑
结合EF Core完成数据库查询(需先安装Microsoft.EntityFrameworkCore及对应数据库Provider,如Microsoft.EntityFrameworkCore.SqlServer):var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); var app = builder.Build(); // 分页排序接口 app.MapGet("/products", async (AppDbContext db, [AsParameters] PaginationParams param) => { var query = db.Products.AsQueryable(); // 动态排序 query = param.IsAscending ? query.OrderBy(p => EF.Property<object>(p, param.SortBy)) : query.OrderByDescending(p => EF.Property<object>(p, param.SortBy)); // 分页计算 var totalItems = await query.CountAsync(); var items = await query .Skip((param.PageIndex - 1) * param.PageSize) .Take(param.PageSize) .ToListAsync(); return Results.Ok(new { TotalItems = totalItems, PageIndex = param.PageIndex, PageSize = param.PageSize, Items = items }); }); // 启用静态文件支持(用于前端页面) app.UseStaticFiles(); app.Run();前端表格实现
在wwwroot目录下创建index.html,通过原生JS渲染分页排序表格:<!DOCTYPE html> <html> <head> <title>Product Grid</title> <style> table { border-collapse: collapse; width: 100%; margin: 20px 0; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { cursor: pointer; background-color: #f5f5f5; } .pagination button { margin: 0 2px; padding: 4px 8px; cursor: pointer; } .active { background-color: #007bff; color: white; border: none; } </style> </head> <body> <table id="productTable"> <thead> <tr> <th data-sort="Id">ID</th> <th data-sort="Name">Name</th> <th data-sort="Price">Price</th> </tr> </thead> <tbody></tbody> </table> <div class="pagination" id="pagination"></div> <script> let currentPage = 1; let currentSortBy = "Id"; let currentIsAscending = true; const pageSize = 10; async function loadProducts() { const res = await fetch(`/products?PageIndex=${currentPage}&PageSize=${pageSize}&SortBy=${currentSortBy}&IsAscending=${currentIsAscending}`); const data = await res.json(); // 渲染表格内容 const tbody = document.querySelector("#productTable tbody"); tbody.innerHTML = data.Items.map(p => ` <tr> <td>${p.Id}</td> <td>${p.Name}</td> <td>$${p.Price.toFixed(2)}</td> </tr> `).join(''); // 渲染分页控件 const pagination = document.querySelector("#pagination"); pagination.innerHTML = ''; const totalPages = Math.ceil(data.TotalItems / pageSize); // 上一页按钮 if (currentPage > 1) { const prevBtn = document.createElement('button'); prevBtn.textContent = 'Prev'; prevBtn.onclick = () => { currentPage--; loadProducts(); }; pagination.appendChild(prevBtn); } // 页码按钮 for (let i = 1; i <= totalPages; i++) { const btn = document.createElement('button'); btn.textContent = i; btn.className = i === currentPage ? 'active' : ''; btn.onclick = () => { currentPage = i; loadProducts(); }; pagination.appendChild(btn); } // 下一页按钮 if (currentPage < totalPages) { const nextBtn = document.createElement('button'); nextBtn.textContent = 'Next'; nextBtn.onclick = () => { currentPage++; loadProducts(); }; pagination.appendChild(nextBtn); } } // 表头排序事件 document.querySelectorAll('#productTable th').forEach(th => { th.addEventListener('click', () => { const sortBy = th.dataset.sort; if (sortBy === currentSortBy) { currentIsAscending = !currentIsAscending; } else { currentSortBy = sortBy; currentIsAscending = true; } currentPage = 1; // 排序后重置到第一页 loadProducts(); }); }); // 初始加载数据 loadProducts(); </script> </body> </html>
方案二:使用前端网格组件(如DataTables.js)
适合快速实现复杂表格功能(含分页、排序、搜索),无需手动编写分页逻辑。
引入DataTables资源
修改index.html,添加CDN链接:<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css"> <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>简化前端代码
利用DataTables自动处理分页排序:<!DOCTYPE html> <html> <head> <title>Product Grid</title> <link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css"> <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script> <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script> </head> <body> <table id="productTable" class="display" style="width:100%"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Price</th> </tr> </thead> <tbody></tbody> </table> <script> $(document).ready(async function() { // 可返回全部数据让DataTables处理,或配置服务器端分页(适合大数据量) const res = await fetch("/products?PageSize=100"); const data = await res.json(); $("#productTable").DataTable({ data: data.Items, columns: [ { data: "Id" }, { data: "Name" }, { data: "Price", render: p => `$${p.toFixed(2)}` } ], paging: true, searching: true, ordering: true }); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者dave
相关产品推荐
相关产品推荐

