ar.gorgin
ar.gorgin

Reputation: 5002

How to get current userId in asp.net core

I use Identity in core.

in startup.

services.AddSingleton<ICurrentUserService, CurrentUserService>();
services.AddHttpContextAccessor();

and in accountcontroller

[ApiController]
[Route("api/[controller]")]
public class AccountController : Controller
{
    private readonly IApplicationUserManager _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public AccountController
    (IApplicationUserManager userManager,
        SignInManager<ApplicationUser> signInManager)
    {
        _userManager = userManager;
        //_roleManager = roleManager;
        _signInManager = signInManager;
    }



    [HttpPost("Login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login(LoginViewModel model)
    {
        try
        {
            await _signInManager.SignOutAsync();

            var result = await _signInManager.PasswordSignInAsync(model.email, model.password, true, false);


            if (result.Succeeded)
            {
                return Json(new { success = true});
            }

            var message = string.Join("; ", ModelState.Values
                .SelectMany(x => x.Errors)
                .Select(x => x.ErrorMessage));

            return Json(new
            {
                success = false,
                Message = message
            });

        }
        catch (Exception e)
        {
            return Json(new
            {
                success = false,
                Message = e.Message
            });
        }

    }

    [HttpPost("logout")]
    public IActionResult LogOut()
    {
        try
        {
            _signInManager.SignOutAsync();
            return Ok(new { success = true });
        }
        catch (Exception e)
        {
            return Ok(new { success = false, Message = e.Message });
        }

    }
}

}

and in CurrentUserService

public class CurrentUserService : ICurrentUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;

public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}

public Guid? UserId => Guid.Parse(_httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? string.Empty);


public string FullName => _httpContextAccessor.HttpContext?.User?.FindFirstValue("FullName") != null
                ? _httpContextAccessor.HttpContext?.User?.FindFirstValue("FullName")
                : _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name);

public string Avatar => _httpContextAccessor.HttpContext?.User?.FindFirstValue("Avatar") != null
    ? _httpContextAccessor.HttpContext?.User?.FindFirstValue("Avatar")
    : "/Themes/img/no_avatar.png";

}

but _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) is null always.

Update :

I add this to startup. it is ok.

   app.UseAuthorization();
   app.UseAuthentication();

Upvotes: 2

Views: 912

Answers (1)

VahidN
VahidN

Reputation: 19136

If you want to access the IHttpContextAccessor in your DbContext class and its overridden SavingChanges method, don't do it! Instead create a SaveChangesInterceptor and then inject your services as usual:

public class AuditableEntitiesInterceptor : SaveChangesInterceptor
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ILogger<AuditableEntitiesInterceptor> _logger;

    public AuditableEntitiesInterceptor(
        IHttpContextAccessor httpContextAccessor,
        ILogger<AuditableEntitiesInterceptor> logger)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

Then you should register your new interceptor:

services.AddSingleton<AuditableEntitiesInterceptor>();

And finally add it/introduce it to EF-Core this way:

services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) => 
optionsBuilder.AddInterceptors(serviceProvider.GetRequiredService<AuditableEntitiesInterceptor>());

Upvotes: 9

Related Questions