255

I have an Article entity in my project which has the ApplicationUser property named Author. How can I get the full object of currently logged ApplicationUser? While creating a new article, I have to set the Author property in Article to the current ApplicationUser.

In the old Membership mechanism it was simple, but in the new Identity approach I don't know how to do this.

I tried to do it this way:

  • Add using statement for Identity extensions: using Microsoft.AspNet.Identity;
  • Then I try to get the current user: ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == User.Identity.GetUserId());

But I get the following exception:

LINQ to Entities does not recognize the method 'System.String GetUserId(System.Security.Principal.IIdentity)' method, and this method cannot be translated into a store expression. Source=EntityFramework

Gustav
  • 53,498
  • 7
  • 29
  • 55
Ellbar
  • 3,984
  • 6
  • 24
  • 36

11 Answers11

471

You should not need to query the database directly for the current ApplicationUser.

That introduces a new dependency of having an extra context for starters, but going forward the user database tables change (3 times in the past 2 years) but the API is consistent. For example the users table is now called AspNetUsers in Identity Framework, and the names of several primary key fields kept changing, so the code in several answers will no longer work as-is.

Another problem is that the underlying OWIN access to the database will use a separate context, so changes from separate SQL access can produce invalid results (e.g. not seeing changes made to the database). Again the solution is to work with the supplied API and not try to work-around it.

The correct way to access the current user object in ASP.Net identity (as at this date) is:

var user = UserManager.FindById(User.Identity.GetUserId());

or, if you have an async action, something like:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

FindById requires you have the following using statement so that the non-async UserManager methods are available (they are extension methods for UserManager, so if you do not include this you will only see FindByIdAsync):

using Microsoft.AspNet.Identity;

If you are not in a controller at all (e.g. you are using IOC injection), then the user id is retrieved in full from:

System.Web.HttpContext.Current.User.Identity.GetUserId();

If you are not in the standard Account controller you will need to add the following (as an example) to your controller:

1. Add these two properties:

    /// <summary>
    /// Application DB context
    /// </summary>
    protected ApplicationDbContext ApplicationDbContext { get; set; }

    /// <summary>
    /// User manager - attached to application DB context
    /// </summary>
    protected UserManager<ApplicationUser> UserManager { get; set; }

2. Add this in the Controller's constructor:

    this.ApplicationDbContext = new ApplicationDbContext();
    this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));

Update March 2015

Note: The most recent update to Identity framework changes one of the underlying classes used for authentication. You can now access it from the Owin Context of the current HttpContent.

ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());

Addendum:

When using EF and Identity Framework with Azure, over a remote database connection (e.g. local host testing to Azure database), you can randomly hit the dreaded “error: 19 - Physical connection is not usable”. As the cause is buried away inside Identity Framework, where you cannot add retries (or what appears to be a missing .Include(x->someTable)), you need to implement a custom SqlAzureExecutionStrategy in your project.

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • 7
    @TBA - thanks, I realized later it's an extension method. Need to add Microsoft.AspNet.Identity using . thanks again – Sentinel Jun 18 '14 at 10:31
  • 3
    Type or namesapce UserStore could not be found.I added using Microsft.AspNet.Indentity – Wasfa Jul 10 '14 at 07:04
  • Why You should not need to query the database directly for the current ApplicationUser? – Yoda Sep 03 '14 at 21:05
  • Isn't the ApplicationUser stored in the current context ? – Bart Calixto Oct 28 '14 at 17:04
  • Doesn't work for me. var user = UserManager.FindById(Context.User.Identity.GetUserId()); Error 1 Using the generic type 'Microsoft.AspNet.Identity.UserManager' requires 1 type argumens. Lookin at the metadata it doesn't even have this method, and the class isn't static. – Ronen Festinger Nov 20 '14 at 15:40
  • Found the solution and posted it here in a comment: http://stackoverflow.com/questions/25483227/asp-net-identity-how-to-get-current-identityuser-applicationuser-where-is-us – Ronen Festinger Nov 20 '14 at 18:09
  • @TrueBlueAussie I had the using statement, but still I had this error. The problem was I was trying to use it outside the controller, From a hub of SignalR, so I had to initialize evertyhing before the call, like that: `ApplicationDbContext applicationDbContext = new ApplicationDbContext(); UserManager userManager = new UserManager(new UserStore(applicationDbContext)); var user = userManager.FindById Context.User.Identity.GetUserId());` – Ronen Festinger Nov 21 '14 at 22:31
  • Just to mention, I saw this code is very time consuming, I will try to use it only once, or try to put it in static properties. – Ronen Festinger Nov 26 '14 at 20:43
  • From what I saw the initialization of it is slow, I don't care if the UserManager is shared between users. It's not different anyhow. I wouldn't want to initialize it for each request. Strange there is no method to get the user object from the context, it only gives you Id or UserName. – Ronen Festinger Nov 27 '14 at 16:24
  • @Ronen Festinger: Sorry, I just saw your *first* comment and now see what you are talking about. Yes *that part* can be made static. – iCollect.it Ltd Nov 27 '14 at 16:41
  • The previous comment has some issues with child custom objects not loading for the ApplicationUser. This is a better code: `private static ApplicationUserManager _userManager = HttpContext.Current.GetOwinContext().GetUserManager(); var user = _userManager.FindByName(userName);` – Ronen Festinger Feb 01 '15 at 22:44
  • Actually, static doesn't work well, because it's not updated, you should use: `private ApplicationUserManager _userManager { get { return HttpContext.GetOwinContext().GetUserManager(); } }` – Ronen Festinger Feb 01 '15 at 23:55
  • @TrueBlueAussie : Do you mean the User's Id in the User table by "GetUserId()"? I mean that for example there is a User table wit ID and UserName columns. When calling SaveChanges() method, I want to use ID rather than UserName in order to add this ID to my Audit / Logging tables. How can I do this? – Jack Mar 19 '15 at 18:25
  • @H.Johnson. Please ask a new question, not via comments. The API means you should not have to hit the database directly for saving changes either. – iCollect.it Ltd Mar 19 '15 at 19:32
  • Is there no way to extend the @User.Identity. class and add other values there? For example I want to get a value from the user, its displayed on every page? Do i really have to do another db access? Surely its already accessing the db somewhere to get the ID and the username? – Zapnologica Apr 23 '15 at 13:17
  • 3
    @Zapnologica: That sounds like a new question (suggest you post it). You can extend the `ApplicationUser` class (application specific) and the `AspNetUsers` table in parallel and they will provide any new fields. Again: Do not hit the database directly! :) – iCollect.it Ltd Apr 23 '15 at 13:48
  • Yes but by overriding the application user, doesn't mean that those fields will always be accesaible from the httpcontext like `User.Identity.UserName` is. – Zapnologica Apr 23 '15 at 17:25
  • @Zapnologica: The Identity is a different animal to the application user. `ApplicationUser` uses `Identity.UserName`, but any extension data is in the `ApplicationUser` (by way of the AspNetUsers table). Either you should work *with* `ApplicationUser` or expect maintenance troubles if you hit the database directly. You have been advised :) – iCollect.it Ltd Apr 24 '15 at 08:01
  • I have `ApplicationUser:IdentityUser` with some of my own properties. How do I get that without accessing db? Your answer is only giving me access to `IdentityUser` stuff – SMUsamaShah May 08 '15 at 18:38
  • 3
    @LifeH2O: The ApplicationUser returned by FindById is *your* class, complete with *your* extra properties. Please try it. – iCollect.it Ltd May 08 '15 at 18:42
  • @TrueBlueAussie I am amazed that this isn't the accepted answer, too often the quick fix is the accepted and best practice answer is not. – hutchonoid May 13 '15 at 14:04
  • @TrueBlueAussie Oh, didn't spot that. :) – hutchonoid May 13 '15 at 15:09
  • 2
    Waiting For your new Workaround :P – Anup Sharma May 30 '15 at 08:50
  • Do you have a new work around as promised at the end of your answer? – Reafidy Aug 05 '15 at 09:54
  • @Reafidy: Yeah, sorry about that. The Owin context on the current HttpContext exposes it now, so I have added an alternative. – iCollect.it Ltd Aug 05 '15 at 14:26
  • Does HttpContext.Current.GetOwinContext().GetUserManager().FindById(HttpContext.Current.User.Identity.GetUserId()) hit the database or not? – Aleksa Feb 09 '16 at 14:04
  • @Aleksa: The `GetUserId()` method *may* hit the database, or it may be cached, but you should not care as that implementation detail is hidden (and it is very fast anyway). Why do you ask? – iCollect.it Ltd Feb 09 '16 at 14:16
  • I asked for GetUserManager().FindById method, because I want to be sure it gets the newest data for User, not something cached. – Aleksa Feb 09 '16 at 14:20
  • @Aleksa: it depends on how the database is modified. If you use a different context to update the database the UserManager will not return the updates. This is why you should only go through the API. – iCollect.it Ltd Feb 13 '16 at 10:56
65

My mistake, I shouldn't have used a method inside a LINQ query.

Correct code:

using Microsoft.AspNet.Identity;


string currentUserId = User.Identity.GetUserId();
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
Rikin Patel
  • 8,848
  • 7
  • 70
  • 78
Ellbar
  • 3,984
  • 6
  • 24
  • 36
  • 3
    User.Identiy.GetUserId does not exist for me. is that i custom method? I only get up to User.Identity – Gerrie Pretorius Jan 08 '14 at 06:05
  • 10
    Nevermind... you need the "using Microsoft.AspNet.Identity;" for that method to be there. – Gerrie Pretorius Jan 08 '14 at 06:36
  • 4
    Just a note, the User object is visible only in Controllers. – Miro J. Jan 31 '14 at 22:49
  • 9
    Surely you should be using `UserManager` methods and not hitting the database directly? – iCollect.it Ltd Apr 02 '14 at 15:07
  • @TrueBlueAussie Could you elaborate a bit on the difference? Both methods would pull data from the database wouldn't they? – Drazen Bjelovuk Nov 11 '14 at 09:33
  • 3
    @Josh Bjelovuk: Never hit a database directly when an API is available. That introduces a new dependency of having an extra context for starters, but going forward the user database tables change (3 times in the past 2 years) but the API is consistent. – iCollect.it Ltd Nov 11 '14 at 09:44
  • @Ellbar I think you should consider changing the accepted answer to Gone Coding's. As you can see, his approach uses the relevant ASP.NET Identity APIs instead of bypassing them and loading directly from the database as you do here. – Zero3 Apr 07 '16 at 08:44
  • var db = new ApplicationDbContext(); string userId = User.Identity.GetUserId().ToString(); – Joseph Poirier Apr 28 '19 at 15:37
33

Its in the comments of the answers but nobody has posted this as the actual solution.

You just need to add a using statement at the top:

using Microsoft.AspNet.Identity;
rtpHarry
  • 13,019
  • 4
  • 43
  • 64
  • 2
    I came here with that exception, I solved it with that `using`. Seeing as 15k people have visited the question I figured it was a helpful answer :) – rtpHarry Nov 28 '14 at 15:26
  • 2
    @TrueBlueAussie, despite not being a direct answer to the OPs question, I feel that mentioning the using is a very useful addition. – StuartQ Jan 23 '15 at 11:55
  • 2
    For clarity, it's because `.GetUserId()` is an extension method – FSCKur Mar 19 '19 at 11:14
11

The code of Ellbar works! You need only add using.

1 - using Microsoft.AspNet.Identity;

And... the code of Ellbar:

2 - string currentUserId = User.Identity.GetUserId(); ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);

With this code (in currentUser), you work the general data of the connected user, if you want extra data... see this link

Diego Borges
  • 342
  • 3
  • 7
  • 5
    It may "work", but it is certainly not *recommended* to bypass the supplied API and hit the database directly If you did use the API you would not need extra work to get the extra data *as it would already be in the `ApplicationUser` object* – iCollect.it Ltd Feb 02 '15 at 00:25
  • I agree! However, resorted to this way because I had already have a system in place today, with a run in the database and I need a simple solution to solve this issue! Certainly, in an early system, I would put objects in their proper classes and identities. – Diego Borges Feb 03 '15 at 02:37
6

As of ASP.NET Identity 3.0.0, This has been refactored into

//returns the userid claim value if present, otherwise returns null
User.GetUserId();
Paul Plato
  • 1,471
  • 6
  • 28
  • 36
6
ApplicationDbContext context = new ApplicationDbContext();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
ApplicationUser currentUser = UserManager.FindById(User.Identity.GetUserId());

string ID = currentUser.Id;
string Email = currentUser.Email;
string Username = currentUser.UserName;
Majid joghataey
  • 1,488
  • 2
  • 17
  • 28
3

Right now the asp.mvc project template creates an account controller that gets the usermanager this way:

HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()

The following works for me:

ApplicationUser user = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(User.Identity.GetUserId());
Liam
  • 27,717
  • 28
  • 128
  • 190
Holger Thiemann
  • 1,042
  • 7
  • 17
3

For MVC 5 just look inside the EnableTwoFactorAuthentication method of ManageController in WebApplication template scaffold, its being done there:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> EnableTwoFactorAuthentication()
        {
            await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
            if (user != null)
            {
                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
            }
            return RedirectToAction("Index", "Manage");
        }

The answer is right there as suggested by Microsoft itself:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

It will have all the additional properties you defined in ApplicationUser class.

Paceman
  • 2,095
  • 4
  • 20
  • 27
1

In case someone is working with Identity users in web forms, I got it working by doing so:

var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var user = manager.FindById(User.Identity.GetUserId());
Jamshaid K.
  • 3,555
  • 1
  • 27
  • 42
0

There is a simple way :

User.Identity.Name

It provides the Id of the current user.

harili
  • 406
  • 9
  • 24
-1

I was successfully available to get Application User By Following Piece of Code

var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
            var user = manager.FindById(User.Identity.GetUserId());
            ApplicationUser EmpUser = user;
Abdul Hannan
  • 424
  • 1
  • 6
  • 20