如何仅对Admin角色用户显示DataTable的编辑/删除操作列
MVC中DataTables根据用户角色隐藏操作列的解决方案
问题背景
我刚接触MVC和JavaScript,在MVC项目中使用DataTables展示数据库产品列表时遇到需求:仅Admin角色用户能看到表格最后一列的编辑、删除按钮,非Admin用户可正常加载表格但需隐藏该操作列。
之前尝试用Razor语法控制表头显示,仅隐藏了表头,操作按钮仍会显示;且在product.js中使用Razor语法无法被识别。用户角色信息存储在数据库的AspNetUsers表中。
解决方案
方法一:前端传递角色状态动态生成列
由于独立JS文件无法解析Razor语法,我们可以在Razor视图中把用户角色状态传递给全局变量,再在JS中根据该变量决定是否渲染操作列。
- 修改
Index.cshtml,在脚本区块添加全局变量:
@section Scripts { <script> // 将用户是否为Admin的状态暴露给全局 window.isAdmin = @User.IsInRole("Admin"); </script> <script src="~/js/product.js"></script> }
- 修改
Index.cshtml中的表头,用Razor判断是否渲染Action列:
<thead> <tr> <th>Id</th> <th>Name</th> <th>Brand</th> <th>Description</th> @if (User.IsInRole("Admin")) { <th>Action</th> } </tr> </thead>
- 修改
product.js,动态生成列配置:
var dataTable; $(document).ready(function () { loadDataTable(); }); function loadDataTable() { // 基础列配置 let columns = [ { data: 'productId', "width": "25%" }, { data: 'productName', "width": "25%" }, { data: 'productBrand', "width": "15%" }, { data: 'productDescription', "width": "10%" } ]; // 仅Admin用户添加操作列 if (window.isAdmin) { columns.push({ data: 'id', "render": function (data) { return `<div class="w-75 btn-group" role="group"> <a href="ProductDT/Edit?id=${data}" class="btn btn-primary mx-2"><i class="bi bi-pencil-square"></i> Edit</a> <a onClick=Delete('ProductDT/Delete?id=${data}') class="btn btn-danger mx-2"><i class="bi bi-trash-fill"></i> Delete</a> </div>`; }, "width": "25%" }); } dataTable = $('#tblData').DataTable({ ajax: { url: '/ProductDT/GetAll' }, columns: columns }); }
方法二:通过DataTables配置控制列可见性
如果不想动态修改列数组,可以直接在DataTables初始化时用columnDefs配置列的可见性。
同样在
Index.cshtml中传递window.isAdmin全局变量(同方法一步骤1)。修改
product.js的DataTables初始化代码:
function loadDataTable() { dataTable = $('#tblData').DataTable({ ajax: { url: '/ProductDT/GetAll' }, columns: [ { data: 'productId', "width": "25%" }, { data: 'productName', "width": "25%" }, { data: 'productBrand', "width": "15%" }, { data: 'productDescription', "width": "10%" }, { data: 'id', "render": function (data) { return `<div class="w-75 btn-group" role="group"> <a href="ProductDT/Edit?id=${data}" class="btn btn-primary mx-2"><i class="bi bi-pencil-square"></i> Edit</a> <a onClick=Delete('ProductDT/Delete?id=${data}') class="btn btn-danger mx-2"><i class="bi bi-trash-fill"></i> Delete</a> </div>`; }, "width": "25%" } ], columnDefs: [ // 控制第5列(索引从0开始)的可见性 { targets: 4, visible: window.isAdmin } ] }); }
- 表头部分同样用Razor判断是否渲染Action列(同方法一步骤2)。
方法三:后端控制返回数据(更安全)
如果担心前端控制被篡改,可以在后端API中根据用户角色决定是否返回操作所需的ID,从根源上限制非Admin用户的操作权限。
- 修改
ProductDTController的GetAll方法:
[HttpGet] public IActionResult GetAll() { bool isAdmin = User.IsInRole("Admin"); // 根据角色决定是否返回操作ID var productList = _db.Products.Select(p => new { p.productId, p.productName, p.productBrand, p.productDescription, Id = isAdmin ? p.Id : (int?)null }).ToList(); return Json(new { data = productList }); }
- 修改
product.js中的操作列渲染逻辑:
{ data: 'id', "render": function (data) { // 非Admin用户无Id,返回空内容 if (!data) return ''; return `<div class="w-75 btn-group" role="group"> <a href="ProductDT/Edit?id=${data}" class="btn btn-primary mx-2"><i class="bi bi-pencil-square"></i> Edit</a> <a onClick=Delete('ProductDT/Delete?id=${data}') class="btn btn-danger mx-2"><i class="bi bi-trash-fill"></i> Delete</a> </div>`; }, "width": "25%", "visible": window.isAdmin }
- 表头部分依旧用Razor判断是否显示(同方法一步骤2)。
内容的提问来源于stack exchange,提问作者Steven Showler
相关产品推荐
相关产品推荐

