ASP.NET MVC模型只读字段自动填充及角色权限配置问题
ASP.NET MVC + Identity 实现Entry模型字段控制方案
1. DevDate字段:只读+创建时自动填充当前时间
模型层配置
在Entry.cs模型中,给DevDate添加只读特性,可选配置数据库自动生成逻辑:
public class Entry { public int Id { get; set; } [ReadOnly(true)] [DatabaseGenerated(DatabaseGeneratedOption.Computed)] // 可选,数据库层面自动生成时间 public DateTime DevDate { get; set; } // 其他字段... }
视图层控制只读
在Create/Edit视图中,将DevDate改为显示控件+隐藏域,禁止手动编辑:
<div class="form-group"> @Html.LabelFor(model => model.DevDate, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.DisplayFor(model => model.DevDate) @Html.HiddenFor(model => model.DevDate) </div> </div>
控制器层赋值(创建时)
若未使用数据库自动生成,在Create的POST方法中手动赋值当前时间:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,DevDate,dev_name,...")] Entry entry) { if (ModelState.IsValid) { entry.DevDate = DateTime.UtcNow; // 推荐用UTC时间 _context.Add(entry); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(entry); }
2. dev_name字段:只读+自动填充当前用户名
模型层配置
添加只读特性标记:
public class Entry { // 其他字段... [ReadOnly(true)] public string dev_name { get; set; } }
视图层控制只读
同DevDate逻辑,用显示控件+隐藏域:
<div class="form-group"> @Html.LabelFor(model => model.dev_name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.DisplayFor(model => model.dev_name) @Html.HiddenFor(model => model.dev_name) </div> </div>
控制器层赋值(创建时)
通过Identity的User.Identity.Name获取当前登录用户名:
[HttpPost] [ValidateAntiForgeryToken] [Authorize] // 确保用户已登录 public async Task<IActionResult> Create([Bind("Id,DevDate,dev_name,...")] Entry entry) { if (ModelState.IsValid) { entry.dev_name = User.Identity.Name; entry.DevDate = DateTime.UtcNow; _context.Add(entry); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(entry); }
3. 基于角色控制非只读字段的编辑权限
假设前4个非只读字段为Field1、Field2、Field3、Field4,其余非只读字段为Field5至FieldN,需在视图和控制器层分别做权限控制:
视图层动态显示编辑控件
根据用户角色判断是否展示可编辑控件:
<!-- 前4个字段:仅角色X/Admin可编辑 --> <div class="form-group"> @Html.LabelFor(model => model.Field1, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @if (User.IsInRole("X") || User.IsInRole("Admin")) { @Html.EditorFor(model => model.Field1, new { htmlAttributes = new { @class = "form-control" } }) } else { @Html.DisplayFor(model => model.Field1) @Html.HiddenFor(model => model.Field1) } @Html.ValidationMessageFor(model => model.Field1, "", new { @class = "text-danger" }) </div> </div> <!-- 重复Field2、Field3、Field4的上述逻辑 --> <!-- 其余字段:仅角色Y/Admin可编辑 --> <div class="form-group"> @Html.LabelFor(model => model.Field5, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @if (User.IsInRole("Y") || User.IsInRole("Admin")) { @Html.EditorFor(model => model.Field5, new { htmlAttributes = new { @class = "form-control" } }) } else { @Html.DisplayFor(model => model.Field5) @Html.HiddenFor(model => model.Field5) } @Html.ValidationMessageFor(model => model.Field5, "", new { @class = "text-danger" }) </div> </div> <!-- 重复Field6至FieldN的上述逻辑 -->
控制器层防篡改验证(可选)
为避免前端篡改数据,在Edit的POST方法中重置无权限字段的值:
[HttpPost] [ValidateAntiForgeryToken] [Authorize(Roles = "X,Y,Admin")] public async Task<IActionResult> Edit(int id, [Bind("Id,DevDate,dev_name,Field1,Field2,Field3,Field4,Field5,...")] Entry entry) { if (id != entry.Id) return NotFound(); var existingEntry = await _context.Entry.FindAsync(id); if (existingEntry == null) return NotFound(); // 限制非X/Admin用户修改前4个字段 if (!(User.IsInRole("X") || User.IsInRole("Admin"))) { entry.Field1 = existingEntry.Field1; entry.Field2 = existingEntry.Field2; entry.Field3 = existingEntry.Field3; entry.Field4 = existingEntry.Field4; } // 限制非Y/Admin用户修改其余字段 if (!(User.IsInRole("Y") || User.IsInRole("Admin"))) { entry.Field5 = existingEntry.Field5; // 其余字段同理赋值 } if (ModelState.IsValid) { try { _context.Update(entry); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!EntryExists(entry.Id)) return NotFound(); else throw; } return RedirectToAction(nameof(Index)); } return View(entry); } private bool EntryExists(int id) { return _context.Entry.Any(e => e.Id == id); }
内容的提问来源于stack exchange,提问作者Alexander Barbu
相关产品推荐
相关产品推荐

