.NET 6中在Repository类使用UserPrincipal出现空对象问题
问题:Repository类中使用UserPrincipal出现空引用错误(.NET 6)
在.NET 6环境下,原本在Controller中使用UserPrincipal功能正常,但将相关代码移至Models目录下的Repository类后,出现空引用错误。希望通过Repository类封装代码简化Controller逻辑,目前除UserPrincipal相关部分外其余功能均正常,求解决思路。
相关代码
using Directory.Services.AccountManagement; using HumanResources.JobsContext; using HumanResources.Models; using HumanResources.Controllers; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Data.SqlClient; public class Repository : Controller { [HttpPost] public ActionResult PostIndexInternal(IFormFile file, Job job) { PrincipalContext pc = new PrincipalContext(ContextType.Domain, "PPS"); UserPrincipal up = UserPrincipal.FindByIdentity(pc, User.Identity.Name); string first = up.GivenName; string last = up.Surname; string full = first + " " + last; if (file != null) { if (file.Length > 0) { //Get File Name var fileName = Path.GetFileName(file.FileName); //Get File Extension var fileExtension = Path.GetExtension(fileName); //Create New File Name based on AD Credentials var newFileName = String.Concat(user, fileExtension); //Creating new object on the database var fileObject = new InternalJob() { IdJob = job.Id, Title = job.Title, EmployeeID = employeeID, FileName = newFileName, EmployeeName = user, CurrentJobTitle = currentPosition, DateApplied = DateTime.Now, Active = true }; using (var target = new MemoryStream()) { file.CopyTo(target); fileObject.FileData = target.ToArray(); } _hrContext.InternalJobs.Add(fileObject); _hrContext.SaveChanges(); return RedirectToAction(nameof(JobsApplied)); } } else if (file == null) { string msg = "Please do not forget to select and upload the Resume"; return Json(msg); } return RedirectToAction(nameof(JobsApplied)); } } //This would be in the HomeController [HttpPost] public IActionResult Example(IFormFile file, Job job) { Repository repository = new Repository(_context); return repository.PostIndexInternal(IFormFile file, Job job); }
解决思路
取消Repository对Controller的继承
Repository是业务/数据访问类,不应该继承Controller。Controller的User属性依赖于请求上下文,直接实例化Repository时该上下文未被初始化,导致User为null引发空引用。将Repository改为普通类,移除Controller继承关系。从Controller传递用户身份信息
在Controller中获取当前用户的User.Identity.Name,将其作为参数传入Repository的方法,而非在Repository内部直接访问User对象。示例修改:// Repository类修改为普通类 public class Repository { private readonly HrContext _hrContext; public Repository(HrContext hrContext) { _hrContext = hrContext; } public ActionResult PostIndexInternal(IFormFile file, Job job, string userName) { PrincipalContext pc = new PrincipalContext(ContextType.Domain, "PPS"); UserPrincipal up = UserPrincipal.FindByIdentity(pc, userName); // 后续逻辑保持不变 } } // Controller调用时传递用户名 [HttpPost] public IActionResult Example(IFormFile file, Job job) { Repository repository = new Repository(_context); return repository.PostIndexInternal(file, job, User.Identity.Name); }添加空引用检查
在使用UserPrincipal返回的对象前,必须检查是否为null,避免空引用异常:UserPrincipal up = UserPrincipal.FindByIdentity(pc, userName); if (up == null) { return new JsonResult("无法获取当前用户的AD信息"); } string first = up.GivenName; string last = up.Surname; string full = first + " " + last;可选:通过IHttpContextAccessor获取上下文(不推荐)
如果必须在Repository中访问HttpContext,可通过依赖注入IHttpContextAccessor实现,但会增加类的耦合度,降低可测试性:- 在Program.cs注册服务:
builder.Services.AddHttpContextAccessor(); - Repository中注入并使用:
public class Repository { private readonly HrContext _hrContext; private readonly IHttpContextAccessor _httpContextAccessor; public Repository(HrContext hrContext, IHttpContextAccessor httpContextAccessor) { _hrContext = hrContext; _httpContextAccessor = httpContextAccessor; } public ActionResult PostIndexInternal(IFormFile file, Job job) { var userName = _httpContextAccessor.HttpContext?.User?.Identity?.Name; if (string.IsNullOrEmpty(userName)) { return new JsonResult("用户未登录"); } // 后续逻辑保持不变 } }
- 在Program.cs注册服务:
内容的提问来源于stack exchange,提问作者sdw
相关产品推荐
相关产品推荐

