You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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实现,但会增加类的耦合度,降低可测试性:

    1. 在Program.cs注册服务:
      builder.Services.AddHttpContextAccessor();
      
    2. 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("用户未登录");
              }
              // 后续逻辑保持不变
          }
      }
      

内容的提问来源于stack exchange,提问作者sdw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:31:24