简体   繁体   中英

IHttpContextAccessor is null in class

I have problem when I'm trying to get httpcontext from IHttpContextAccessor field is always null in class.

There is my startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddDistributedMemoryCache();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddTransient<IUserContextServices, UserContextService>();
    services.AddSession(options =>
    {
        options.Cookie.Name = ".AdventureWorks.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(10);
    });
}

This is My UserContext Class which implements IUserContext interface

public class UserContextService : IUserContextServices
{
    private readonly IHttpContextAccessor contextAccessor;
    PQADBContext _context = new PQADBContext();

    public UserContextService(IHttpContextAccessor accessor)
    {
        contextAccessor = accessor;
    }

   public UserContextService()
    {

    }

    public HttpContext Context
    {
        get
        {
            return contextAccessor.HttpContext;
        }
    }
   public int UserID()
    {
       return Context.Session.GetID("UserID").ConvertToInt();
    }
    public bool isLogin()
    {
        return Context.Session.GetBoolean("isLogin").ConvertToBool();
    }
      public UserAccount CreateSession(LoginViewModel logindata, bool EncryptPwd = true)
    {
        string error;
        error = "";
        try
        {
            string EncPwd = EncryptPwd ? EncryptDecryptHelper.Encrypt(logindata.Password) : logindata.Password;
            var UserDetail =_context.UserAccount.Where(e => e.P_No == logindata.PNo && e.Password == EncPwd).SingleOrDefault();


            if (UserDetail != null)
            {

                //HttpContext.Session.SetInt32()

                // ///put all the properties in session variables
                 Context.Session.SetBoolean("isLogin", true);
                Context.Session.SetID("UserID",UserDetail.AccountId);
                Context.Session.SetID("P_No",Convert.ToInt32(UserDetail.P_No));
                Context.Session.SetBoolean("isActive", true);
                Context.Session.SetBoolean("Email", true);
                Context.Session.SetID("RoleId", 1);
                Context.Session.SetString("userName", "admin"); 
   }

httpContext available in above class and also set the Session values but when i try to access httpcontext in this class it gives me null object reference

public class UserService
{
   private readonly IHttpContextAccessor contextAccessor;
    public IUserContextServices _userContext = new UserContextService();
   public UserService()
    {  
    }
 public bool CreateEmployee(AppEmployees appemployee, int RoleId, bool isEmailSend, out string error)
    {
appemployee.CreatedBy = _userContext.UserID(); //this line shows null reference exception
        appemployee.CreatedDate = DateTime.Now;
}

You are newing up the UserContextService using the parameterless constructor

public IUserContextServices _userContext = new UserContextService();

instead of relying on Dependency Injection.

You need to configure your UserService to be used with your DI container - via constructor injection that would be

public class UserService
{
    private readonly IUserServiceContext _userServiceContext;

    public UserService(IUserServiceContext userServiceContext)
    {
        _userServiceContext = userServiceContext;
    }
}

You will also need to amend your Startup.cs to register the UserService and you may want it to implement an interface too

Why do you use default constructor in your UserService?

You use next code:

public IUserContextServices _userContext = new UserContextService();

Of course here you have null for IHttpContextAccessor .

You need to use DI in your UserService.

Example:

private readonly IUserContextService _userContextService;
public UserService(IUserContextService userContextService)
{  
    _userContextService = userContextService;
}

There is good post about DI in .NET Core.

If you have set UserId directly as

public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
    UserId = httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
}

This way you might get null UserId most of the time instead create httpContextAccessor field first like

public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
     this.httpContextAccessor = httpContextAccessor;
}
public string UserId { get { return httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); } }

Then get UserId, this way the problem of getting null UserId will be resolved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM