如何在填写表单时将当前Identity用户设置为模型属性?
解决EF中传递当前用户到Reports模型的问题
你现在遇到的核心问题是:试图从视图传递用户对象到控制器,但模型绑定无法直接把字符串(用户名/ID)转换成IdentityUser实体,而且这种方式还存在安全风险。下面给你两种靠谱的解决方案,优先推荐第一种:
1. 优化模型结构,控制器直接获取当前用户(推荐)
首先,给你的Reports模型添加外键属性,这是EF处理导航属性的标准做法,能避免很多映射问题:
public class Reports { [Key] public int ReportId { get; set; } public string Name { get; set; } // 添加用户外键(必须和IdentityUser的主键类型一致,默认是string) public string UserId { get; set; } // 配置外键与导航属性的关联 [ForeignKey(nameof(UserId))] public IdentityUser User { get; set; } }
接下来,修改视图,不需要传递任何用户相关的隐藏字段——因为控制器可以直接从请求上下文获取当前登录用户,既安全又简单:
@model Reports @using Microsoft.AspNetCore.Identity @inject UserManager<IdentityUser> UserManager <body> <div class="container1"> <form asp-action="Submit" method="post" role="form"> <div class="form-group row"> <label asp-for="Name" class="col-md-2 control-label"></label> <div class="col-md-5"> <input asp-for="Name" class="form-control" /> </div> </div> <!-- 移除原来的User隐藏字段,不需要从视图传用户信息 --> <div class="form-group row"> <div class="col-md-offset-2 col-md-5"> <input type="submit" class="btn btn-primary" value="Next" /> </div> </div> </form> </div> </body>
最后,在控制器的Submit方法里,通过UserManager获取当前用户,给模型赋值后保存:
public class ReportsController : Controller { private readonly UserManager<IdentityUser> _userManager; private readonly YourDbContext _dbContext; // 替换成你的DbContext类名 // 构造函数注入依赖 public ReportsController(UserManager<IdentityUser> userManager, YourDbContext dbContext) { _userManager = userManager; _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> Submit(Reports model) { if (!ModelState.IsValid) { return View(model); } // 获取当前登录用户的ID(最直接的方式) var currentUserId = _userManager.GetUserId(User); model.UserId = currentUserId; // 如果你需要完整的IdentityUser对象,也可以这样获取: // var currentUser = await _userManager.GetUserAsync(User); // model.User = currentUser; _dbContext.Reports.Add(model); await _dbContext.SaveChangesAsync(); return RedirectToAction("Index"); // 替换成你要跳转的页面 } }
2. 如果坚持从视图传用户ID(不推荐)
如果你一定要从视图传递用户ID,那可以修改视图里的隐藏字段,传递用户ID而非用户名:
<input asp-for="UserId" type="hidden" value="@UserManager.GetUserId(User)" />
然后控制器里直接接收model.UserId,和上面的控制器逻辑一样。但这种方式不如控制器直接获取安全——因为隐藏字段可以被恶意篡改,而从HttpContext获取的用户信息是经过身份验证的,无法伪造。
为什么你原来的方式不行?
你原来的代码里@UserManager.GetUserName()缺少参数,正确写法是@UserManager.GetUserName(User),但就算传对了用户名,模型绑定也不会自动去数据库查询对应的IdentityUser实体并赋值给model.User——EF需要的是实体引用或外键值,不是字符串形式的用户名/ID。
内容的提问来源于stack exchange,提问作者Fintan Roche
相关产品推荐
相关产品推荐

