ChatGPT解决这个技术问题 Extra ChatGPT

How to get the current logged in user ID in ASP.NET Core?

I've done this before with MVC5 using User.Identity.GetUserId() but that doesn't seem to work here. The User.Identity doesn't have the GetUserId() method.

I am using Microsoft.AspNet.Identity.

try this System.Web.HttpContext.Current.User.Identity.Name?
Thank you @PravinDeshmukh but that returns the name of the user and not the id
It should work. See the samples in asp.net github.com/aspnet/Identity/blob/…. Just make sure user is logged in. @PravinDeshmukh, never use System.Web.HttpContext.Current in vnext :)
Hi @user960567, can you please tell us why ?
@PravinDeshmukh because it will not work on .NET core and there is no System.Web dependency.

T
TanvirArjel

Update in ASP.NET Core Version >= 2.0

In the Controller:

public class YourControllerNameController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    
    public YourControllerNameController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task<IActionResult> YourMethodName()
    {
        var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) // will give the user's userId
        var userName =  User.FindFirstValue(ClaimTypes.Name) // will give the user's userName
        
        // For ASP.NET Core <= 3.1
        ApplicationUser applicationUser = await _userManager.GetUserAsync(User);
        string userEmail = applicationUser?.Email; // will give the user's Email

       // For ASP.NET Core >= 5.0
       var userEmail =  User.FindFirstValue(ClaimTypes.Email) // will give the user's Email
    }
}

In some other class:

public class OtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public OtherClass(IHttpContextAccessor httpContextAccessor)
    {
       _httpContextAccessor = httpContextAccessor;
    }

   public void YourMethodName()
   {
      var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
   }
}

Then you should register IHttpContextAccessor in the Startup class as follows:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

For more readability write extension methods as follows:

public static class ClaimsPrincipalExtensions
{
    public static T GetLoggedInUserId<T>(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (typeof(T) == typeof(string))
        {
            return (T)Convert.ChangeType(loggedInUserId, typeof(T));
        }
        else if (typeof(T) == typeof(int) || typeof(T) == typeof(long))
        {
            return loggedInUserId != null ? (T)Convert.ChangeType(loggedInUserId, typeof(T)) : (T)Convert.ChangeType(0, typeof(T));
        }
        else
        {
            throw new Exception("Invalid type provided");
        }
    }

    public static string GetLoggedInUserName(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Name);
    }

    public static string GetLoggedInUserEmail(this ClaimsPrincipal principal)
    {
        if (principal == null)
            throw new ArgumentNullException(nameof(principal));

        return principal.FindFirstValue(ClaimTypes.Email);
    }
}

Then use as follows:

public class YourControllerNameController : Controller
{
    public IActionResult YourMethodName()
    {
        var userId = User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
        var userName = User.GetLoggedInUserName();
        var userEmail = User.GetLoggedInUserEmail();
    }
}

public class OtherClass
{
     private readonly IHttpContextAccessor _httpContextAccessor;
     public OtherClass(IHttpContextAccessor httpContextAccessor)
     {
         _httpContextAccessor = httpContextAccessor;
     }

     public void YourMethodName()
     {
         var userId = _httpContextAccessor.HttpContext.User.GetLoggedInUserId<string>(); // Specify the type of your UserId;
     }
}

But User is returning null in my case? Where am I doing wrong?
Are you sure that you are logged in with a user?
My scenario is like I want the username of the user logged in my system. Let it be Ubuntu or Windows? And as I'm testing this in windows I'm logged in under my namee. But it's returning null.
Then have to see your code! May be any external agent playing a role here.
I've found that if you've got a null result from User.Identity.Name, it could be because Anonymous Authentication is enabled. I was able to get User.Identity.Name to return my domain and user name by expanding Properties > launchSettings.json, and setting anonymousAuthentication to false, and windowsAuthentication to true.
A
AmiNadimi

Until ASP.NET Core 1.0 RC1 :

It's User.GetUserId() from System.Security.Claims namespace.

Since ASP.NET Core 1.0 RC2 :

You now have to use UserManager. You can create a method to get the current user :

private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);

And get user information with the object :

var user = await GetCurrentUserAsync();

var userId = user?.Id;
string mail = user?.Email;

Note : You can do it without using a method writing single lines like this string mail = (await _userManager.GetUserAsync(HttpContext.User))?.Email, but it doesn't respect the single responsibility principle. It's better to isolate the way you get the user because if someday you decide to change your user management system, like use another solution than Identity, it will get painful since you have to review your entire code.


I have the System.Security.Claims namespace and the Microsoft.AspNet.Identity assembly.
I think that this answer is better than the accepted answer especially since asp.net core is promoting dependency injection.
Seems wrong way because userManager will make a request to database in order to retrieve information about the user. And in this case the userId was already available in HttpContext.User
@incognito The identifier was just an example but you can get all the information you need with the user's object
@Adrien but the question was how to get User Id. Just wanted to say that provided way is not the most efficient. For this case I would prefer answer by Soren or the shorter version which can be found in comments.
H
Hamza Khanzada

you can get it in your controller:

using System.Security.Claims;
var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

or write an extension method like before .Core v1.0

using System;
using System.Security.Claims;

namespace Shared.Web.MvcExtensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static string GetUserId(this ClaimsPrincipal principal)
        {
            if (principal == null)
                throw new ArgumentNullException(nameof(principal));

            return principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        }
    }
}

and get wherever user ClaimsPrincipal is available :

using Microsoft.AspNetCore.Mvc;
using Shared.Web.MvcExtensions;

namespace Web.Site.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return Content(this.User.GetUserId());
        }
    }
}

Shorter version: var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
Note that this extension method only works for User inside controllers, not view components, as the view component User is of IPrincipal
@AK you can use Convert.ToInt32(User.FindFirstValue(ClaimTypes.NameIdentifier)) to get integer UserId
@HamzaKhanzada Yep, it works, but looks so long and ugly.
this code returns 204 , No Content . any help?
n
niico

I included using System.Security.Claims and I could access the GetUserId() extension method

NB: I had the using Microsoft.AspNet.Identity already but couldn't get the extension method. So I guess both of them have to be used in conjunction with one another

using Microsoft.AspNet.Identity;
using System.Security.Claims;

EDIT: This answer is now outdated. Look at Soren's or Adrien's answer for a dated way of achieving this in CORE 1.0


This was the secret sauce, but for anyone lookign after you add these usings it is... var userId = User.GetUserId();
the .GetUserId() Extension from ClaimsPrincipal (Controller.User) has been move to => UserManager.GetUserId(User);
using System.Security.Claims; var userId = this.User.FindFirst(ClaimTypes.NameIdentifier);
Thumbs up for previously valid answer, and correctly identifying new "correct" answer.
Sorry what is new correct answer? The EDIT says this is dated and 2 other answers are dated???
A
AmiNadimi

For .NET Core 2.0 Only The following is required to fetch the UserID of the logged-in User in a Controller class:

var userId = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

or

var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);

e.g.

contact.OwnerID = this.User.FindFirstValue(ClaimTypes.NameIdentifier);

M
Menno Guldemond

As stated somewhere in this post, the GetUserId() method has been moved to the UserManager.

private readonly UserManager<ApplicationUser> _userManager;

public YourController(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

public IActionResult MyAction()
{
    var userId = _userManager.GetUserId(HttpContext.User);

    var model = GetSomeModelByUserId(userId);

    return View(model);
}

If you started an empty project you might need to add the UserManger to your services in startup.cs. Otherwise this should already be the case.


M
Mansur Haider

you have to import Microsoft.AspNetCore.Identity & System.Security.Claims

// to get current user ID
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

// to get current user info
var user = await _userManager.FindByIdAsync(userId);

from all this anwsers yours is the only one that works with ASP.NET CORE v 2.0. Congratz!
this is it. Anybody from .NET Core 2.0 and above, this is your answer
Tested on .NET Core 3.1 in a Web API + JWT setting. I want the currently signed in user in a base controller, this isn't efficient, querying the user from the database for every request, etc. Is there any way to get the current user without querying the database?
why does mine return "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" for User.FindFirstValue(ClaimTypes.NameIdentifier);?
S
Sum None

In .net core 3.1 (and other more recent versions), you can use:

private readonly UserManager<IdentityUser> _userManager;

public ExampleController(UserManager<IdentityUser> userManager)
{
    _userManager = userManager;
}

Then:

string userId = _userManager.GetUserId(User);

Or async:

var user = await _userManager.GetUserAsync(User);
var userId = user.Id;

At this point, I'm trying to figure out why you'd use one over the other. I know the general benefits of async, but see both of these used frequently. Please post some comments if anyone knows.


It works where can I find the official documentations for these?
@KrishnadasPC Good question. I'm not sure. However, I pulled them from somewhere like here: docs.microsoft.com/en-us/aspnet/core/security/authentication/…
j
jv_

For ASP.NET Core 2.0, Entity Framework Core 2.0, AspNetCore.Identity 2.0 api (https://github.com/kkagill/ContosoUniversity-Backend):

The Id was changed to User.Identity.Name

    [Authorize, HttpGet("Profile")]
    public async Task<IActionResult> GetProfile()
    {
        var user = await _userManager.FindByIdAsync(User.Identity.Name);

        return Json(new
        {
            IsAuthenticated = User.Identity.IsAuthenticated,
            Id = User.Identity.Name,
            Name = $"{user.FirstName} {user.LastName}",
            Type = User.Identity.AuthenticationType,
        });
    }

Response:

https://i.stack.imgur.com/rnZ4y.png


Based on my test, this.User.Identity.Name tends to be the username though. On my test, the username is an email, be the user logs-in from registration or logs-in from external login (e.g., Facebook, Google). Following code returns the userId. I uses an auto-incremented primary key for my identity user table, hence the int.Parse. int userId = int.Parse(this.User.FindFirstValue(ClaimTypes.NameIdentifier));
FindByIdAsync doesn't work as you are providing a username. It works when you replace it by FindByNameAsync.
D
David Liang

For ASP.NET 5.0, I have an extension method as follow:

using System;
using System.ComponentModel;
using System.Security.Claims;

namespace YOUR_PROJECT.Presentation.WebUI.Extensions
{
    public static class ClaimsPrincipalExtensions
    {
        public static TId GetId<TId>(this ClaimsPrincipal principal)
        {
            if (principal == null || principal.Identity == null || 
                !principal.Identity.IsAuthenticated)
            {
                throw new ArgumentNullException(nameof(principal));
            }

            var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);

            if (typeof(TId) == typeof(string) || 
                typeof(TId) == typeof(int) || 
                typeof(TId) == typeof(long) || 
                typeof(TId) == typeof(Guid))
            {
                var converter = TypeDescriptor.GetConverter(typeof(TId));

                return (TId)converter.ConvertFromInvariantString(loggedInUserId);
            }

            throw new InvalidOperationException("The user id type is invalid.");
        }

        public static Guid GetId(this ClaimsPrincipal principal)
        {
            return principal.GetId<Guid>();
        }
    }
}

So you can use it like:

using Microsoft.AspNetCore.Mvc;
using YOUR_PROJECT.Presentation.WebUI.Extensions;

namespace YOUR_PROJECT.Presentation.WebUI.Controllers
{
    public class YourController :Controller
    {
        public IActionResult YourMethod()
        {
            // If it's Guid
            var userId = User.GetId();

            // Or
            // var userId = User.GetId<int>();

            return View();
        }
    }
}

on principal, FindFirstValue is missing, it was good if you noted down the extra packages we need
Was it missing Microsoft.AspNet.Identity? I did this project long time ago, and I don't remember what package that was, and I don't have a reference to the project now. So if you find out of it, please suggest an edit.
Microsoft.Extensions.Identity.Code, that's the package... and I also had the issue that in my service I referenced the System.Web.MVC or something like that so the User I was trying to pass was IPrincipal instead of ClaimPrincipal (I'm migrating from .NET 4.7 to .net core just because I can't publish my old project (non-core) in Rider, and my PC got no more space for VS to try that)
It's seem that new projects (not sure about .Net 5, surely 6, should reference framework instead of looking up every reference) this can be done as the sample project, by adding the... <PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> found sample, seem to be much older than .net 5
P
Peter Kühne

in the APiController

User.FindFirst(ClaimTypes.NameIdentifier).Value

Something like this you will get the claims


A
Ahmad

Although Adrien's answer is correct, you can do this all in single line. No need for extra function or mess.

It works I checked it in ASP.NET Core 1.0

var user = await _userManager.GetUserAsync(HttpContext.User);

then you can get other properties of the variable like user.Email. I hope this helps someone.


The reason why I'm using a method is to respect the single responsability principle. If you don't isolate the way you get the user, it will be painfull if someday you decide to modify you user management system, like use another solution than Identity.
H
HO3EiN

For getting current user id in razor views, we can inject UserManager in the view like this:

@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> _userManager
@{ string userId = _userManager.GetUserId(User); }

I hope you find it useful.


M
Maksud

User.Identity.GetUserId();

does not exist in asp.net identity core 2.0. in this regard, i have managed in different way. i have created a common class for use whole application, because of getting user information.

create a common class PCommon & interface IPCommon adding reference using System.Security.Claims

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Common.Web.Helper
{
    public class PCommon: IPCommon
    {
        private readonly IHttpContextAccessor _context;
        public PayraCommon(IHttpContextAccessor context)
        {
            _context = context;
        }
        public int GetUserId()
        {
            return Convert.ToInt16(_context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
        }
        public string GetUserName()
        {
            return _context.HttpContext.User.Identity.Name;
        }

    }
    public interface IPCommon
    {
        int GetUserId();
        string GetUserName();        
    }    
}

Here the implementation of common class

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Pay.DataManager.Concreate;
using Pay.DataManager.Helper;
using Pay.DataManager.Models;
using Pay.Web.Helper;
using Pay.Web.Models.GeneralViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Pay.Controllers
{

    [Authorize]
    public class BankController : Controller
    {

        private readonly IUnitOfWork _unitOfWork;
        private readonly ILogger _logger;
        private readonly IPCommon _iPCommon;


        public BankController(IUnitOfWork unitOfWork, IPCommon IPCommon, ILogger logger = null)
        {
            _unitOfWork = unitOfWork;
            _iPCommon = IPCommon;
            if (logger != null) { _logger = logger; }
        }


        public ActionResult Create()
        {
            BankViewModel _bank = new BankViewModel();
            CountryLoad(_bank);
            return View();
        }

        [HttpPost, ActionName("Create")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Insert(BankViewModel bankVM)
        {

            if (!ModelState.IsValid)
            {
                CountryLoad(bankVM);
                //TempData["show-message"] = Notification.Show(CommonMessage.RequiredFieldError("bank"), "Warning", type: ToastType.Warning);
                return View(bankVM);
            }


            try
            {
                bankVM.EntryBy = _iPCommon.GetUserId();
                var userName = _iPCommon.GetUserName()();
                //_unitOfWork.BankRepo.Add(ModelAdapter.ModelMap(new Bank(), bankVM));
                //_unitOfWork.Save();
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveMessage(), "Success", type: ToastType.Success);
            }
            catch (Exception ex)
            {
               // TempData["show-message"] = Notification.Show(CommonMessage.SaveErrorMessage("bank"), "Error", type: ToastType.Error);
            }
            return RedirectToAction(nameof(Index));
        }



    }
}

get userId and name in insert action

_iPCommon.GetUserId();

Thanks, Maksud


Do you have to register IHttpContextAccessor in Startup.cs?
No REMESQ , i did not inject this into startup, but working in my application
O
Ogglas

If you are using JWT tokens this code works:

User.FindFirstValue("sub");

M
Mosta

use can use

string userid = User.FindFirst("id").Value;

for some reason NameIdentifier now retrieve the username (.net core 2.2)


j
jelde015

Make sure that you have enable windows authentication. If you have anonymous authentication enabled you may be getting a null string.

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio


Z
Zeeshan Safdar

I know there are many answers posted already, but maybe it will help someone as it did for me.

I mixed two solutions into one, and I am able to get the logged-in User and its Data. I was using DotNet 5. Following code, help to get the logged-in User.

var user = await _userManager.FindByNameAsync(HttpContext.User.Identity.Name);

I used the following package for _userManager

using Microsoft.AspNetCore.Identity;

And for HttpContext, I inherit my Controller from ControllerBase, and for ControllerBase Class I was using the following package

using Microsoft.AspNetCore.Mvc;

D
DavidLyonsGarcia

TLDR:

In the Controler add:

using System.Security.Claims; 

and then you can use:

var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

endof TLDR;

Just an easy way in dot net 6 to test how to get the userID and test it in the default Blazor WebAssembly Core Hosted:

I added a String in WeatherForecast class named userId public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public string? Summary { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string userId { get; set; } = "nope"; } Then in the WeatherForecastController

I add using System.Security.Claims;

In the GET method I set WeatherForecast.userId to User.FindFirstValue(ClaimTypes.NameIdentifier): public IEnumerable Get() { return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)], userId = User.FindFirstValue(ClaimTypes.NameIdentifier) }) .ToArray(); }

And finally in the FetchData.razor I modify the table to:

    <table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
            <th>User Id</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
                <td>@forecast.userId</td>
            </tr>
        }
    </tbody>
</table>

https://i.stack.imgur.com/Fg9c7.png

I hope it helps because in net core 6 sometimes it's quite difficult to find the answers


D
Diego Venâncio

As an administrator working on other people's profile and you need to get the Id of the profile you are working on, you can use a ViewBag to capture the Id e.g ViewBag.UserId = userId; while userId is the string Parameter of the method you are working on.

    [HttpGet]

    public async Task<IActionResult> ManageUserRoles(string userId)
    {

          ViewBag.UserId = userId;


        var user = await userManager.FindByIdAsync(userId);

        if (user == null)
        {
            ViewBag.ErrorMessage = $"User with Id = {userId} cannot be found";
            return View("NotFound");
        }

        var model = new List<UserRolesViewModel>();

        foreach (var role in roleManager.Roles)
        {
            var userRolesViewModel = new UserRolesViewModel
            {
                RoleId = role.Id,
                RoleName = role.Name
            };

            if (await userManager.IsInRoleAsync(user, role.Name))
            {
                userRolesViewModel.IsSelected = true;
            }
            else
            {
                userRolesViewModel.IsSelected = false;
            }

            model.Add(userRolesViewModel);
        }
        return View(model);
    }

E
Elan Hasson

If you want this in ASP.NET MVC Controller, use

using Microsoft.AspNet.Identity;

User.Identity.GetUserId();

You need to add using statement because GetUserId() won't be there without it.


Yea, I included in the question that i have the "using Microsoft.AspNet.Identity". I figured out how to solve it though with my answer on the post
FWIW it's (now) User.GetUserId() and not User.Identity.GetUserId()
The question was and is abou asp.net CORE which has the namespace Microsoft.AspNetCore.Identity; and NOT Microsoft.AspNet.Identity; And using that new namespace there is NO GetUserId() extension method. THIS ANSWER IS WRONG!