Afaq Rajput
Afaq Rajput

Reputation: 123

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;
}

Upvotes: 2

Views: 6463

Answers (3)

Ishant Sitaula
Ishant Sitaula

Reputation: 154

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.

Upvotes: 0

Alexander I.
Alexander I.

Reputation: 2714

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.

Upvotes: 2

ste-fu
ste-fu

Reputation: 7482

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

Upvotes: 3

Related Questions