74

I have some tables that have a uniqueidentifier UserID that relates to aspnet_Users.UserID. When the user submits some data for those tables, since the controller method has an [Authorize] I get a User object. I can get the username with User.Identity.Name, but how do I get the UserID to be able to establish (the ownership) relationship?

Kris
  • 40,604
  • 9
  • 72
  • 101
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622

11 Answers11

87

It seems you cannot get it from the User object but you can get it this way:

Guid userGuid = (Guid)Membership.GetUser().ProviderUserKey;
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • Really? it doesn't require a string? /me checks msdn: http://msdn.microsoft.com/en-us/library/system.web.security.membership.getuser.aspx . Sh|t! u're right! good find :) – Pure.Krome May 30 '09 at 14:35
  • 16
    In the OAuth stuff that has been introduced, this doesn't work (null returned). In ASP.Net 4 MVC you can use the WebSecurity.CurrentUserId property – Dan Oct 14 '12 at 21:05
  • 2
    @Dann it appears that in ASP.Net MVC 5 this no longer works, or they changed the using statements (was using System.Web.Security). Any ideas? – Jed Grant Aug 09 '13 at 18:01
  • 9
    **MVC 5** solution: http://stackoverflow.com/questions/18448637/how-to-get-current-user-and-how-to-use-user-class-in-mvc5/18451374#18451374 – Adam Szabo Aug 26 '13 at 19:20
31

Here is the solution:

Include:

using Microsoft.AspNet.Identity;

Then use extension methods:

User.Identity.GetUserId();
faisale
  • 1,435
  • 14
  • 14
28

Firstly, this answer is not strictly an MVC answer, but an ASP.NET answer. The fact that your site is MVC is irrelevant to solving the problem, in this case.


Hmm. I'm not very sure how you are handling your users in your system but it sounds like you using the (very evil) asp.net membership provider that comes out of the box with .net. This is hinted by the fact that you said

  • aspnet_Users.UserID
  • UserID is a uniqueidentifier (read: GUID).

With the default forms authentication system, which uses the default FormsIdentity, it only has a single property called Name (as you correctly noted). This means it has only one value where to place some unique user information. In your case, you are putting Name/UserName/DisplayName, in the Name property. I'm assuming this name is their Display Name and it is unique. Whatever value you are putting in here, it HAS TO BE UNIQUE.

From this, you can grab the user's guid.

Check this out.

using System.Web.Security;

....

// NOTE: This is a static method .. which makes things easier to use.
MembershipUser user = Membership.GetUser(User.Identity.Name);
if (user == null)
{
    throw new InvalidOperationException("User [" + 
        User.Identity.Name + " ] not found.");
}

// Do whatever u want with the unique identifier.
Guid guid = (Guid)user.ProviderUserKey;

So, every time you wish to grab the user information, you need to grab it from the database using the static method above.

Read all about the Membership class and MembershipUser class on MSDN.

Bonus Answer / Suggestion

As such, i would CACHE that result so you don't need to keep hitting the database.

... cont from above....
Guid guid = (Guid)user.ProviderUserKey;

Cache.Add(User.Identity.Name, user.UserID); // Key: Username; Value: Guid.

Otherwise, you can create your own Identity class (which inherits from IIdentity) and add your own custom properties, like UserID. Then, whenever you authenticate (and also on every request) you can set this value. Anyway, this is a hard core solution, so go with the caching, right now.

HTH

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 1
    Is that the way to do it? Making the name of the user unique? What do we have IDs for at all then? – Pablo Fernandez May 29 '09 at 13:21
  • 4
    OT: Why do you claim the ASP.NET Membership is evil? – eduncan911 May 29 '09 at 20:10
  • 5
    @Eric: because i personally feel that it's a massively overengineered solution for the majority of scenario's. For example, how many times do u see a solution that shares a common sql server where the users are shared across databases, on that same sql server? All those tables and stored procs, which can be cut down to just one or two for the majority of scenario's people do. Summary: massive bloat. Over enginereed. Side note: OpenID FTW now :) – Pure.Krome May 30 '09 at 14:32
  • @J. Pablo: no mate. The ID is the main thing that is unique, but the Membership.GetUser(string) gets the user by the string provided -> generally their username. If u don't provide that string, it uses the current value for whoever is logged in, assuming someone IS logged in. That value is the equivalent of User.Identity.Name. – Pure.Krome May 30 '09 at 14:37
18

User.Identity is an IPrincipal - typically of type System.Web.Security.FormsIdentity

It doesn't know anything about UserIDs - it's just an abstraction of the concept of an 'identity'.

The IIdentity interface only has 'Name' for a user, not even 'Username'.

If you're using MVC4 with the default SimpleMembershipProvider you can do this:

WebSecurity.GetUserId(User.Identity.Name)   // User is on ControllerBase

(Where WebSecurity is in the nuget package Microsoft.AspNet.WebPages.WebData in WebMatrix

You can also use

WebSecurity.CurrentUserName
WebSecurity.CurrentUserId

(if you're using ASPNetMembershipProvider which is the older more complex ASPNET membership system then see the answer by @eduncan911)

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • +1 for `WebSecurity.CurrentUserId`. Even the templated AccountController uses `WebSecurity.GetUserId(User.Identity.Name)` which seems a little daft when it has `CurrentUserId` available. – iCollect.it Ltd Oct 23 '13 at 13:23
11

If you are using the ASP.NET Membership (which in turn uses the IPrincipal object):

using System.Web.Security;
{
  MembershipUser user = Membership.GetUser(HttpContext.User.Identity.Name);
  Guid guid = (Guid)user.ProviderUserKey;
}

User.Identity always returns the state of the current user, logged in or not.

Anonymous or not, etc. So a check for is logged in:

if (User.Identity.IsAuthenticated)
{
  ...
}

So, putting it all together:

using System.Web.Security;
{
  if (User.Identity.IsAuthenticated)
  {
    MembershipUser user = Membership.GetUser(HttpContext.User.Identity.Name);
    Guid guid = (Guid)user.ProviderUserKey;
  }
}
eduncan911
  • 17,165
  • 13
  • 68
  • 104
6

Best Option to Get User ID

Add Below references

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin.Security;*

public myFunc()
{
   .....
   // Code which will give you user ID is 
   var tmp = User.Identity.GetUserId();

}
user3175805
  • 61
  • 1
  • 1
3

If you are using your own IPrincipal object for authorization, you just need to cast it to access the Id.

For example:

public class MyCustomUser : IPrincipal
{
    public int UserId {get;set;}

    //...Other IPrincipal stuff
}

Here is a great tutorial on creating your own Form based authentication.

http://www.codeproject.com/KB/web-security/AspNetCustomAuth.aspx

That should get you on the right path to creating an authentication cookie for your user and accessing your custom user data.

ebrown
  • 811
  • 1
  • 8
  • 13
2
using System.Web.Security;

MembershipUser user = Membership.GetUser(User.Identity.Name); 
int id = Convert.ToInt32(user.ProviderUserKey);
Koraktor
  • 41,357
  • 10
  • 69
  • 99
1

Simple....

int userID = WebSecurity.CurrentUserId;
kleopatra
  • 51,061
  • 28
  • 99
  • 211
Izztraab
  • 17
  • 2
1

Its the ProviderUserKey property.

System.Web.Security.MembershipUser u;
u.ProviderUserKey
Alex
  • 34,776
  • 10
  • 53
  • 68
0

Usually you can just use WebSecurity.currentUserId, but if you're in AccountController just after the account has been created and you want to use the user id to link the user to some data in other tables then WebSecurity.currentUserId (and all of the solutions above), unfortunately, in that case returns -1, so it doesn't work.

Luckily in this case you have the db context for the UserProfiles table handy, so you can get the user id by the following:

UserProfile profile = db.UserProfiles.Where(
    u => u.UserName.Equals(model.UserName)
).SingleOrDefault();

I came across this case recently and this answer would have saved me a whole bunch of time, so just putting it out there.

james_s_tayler
  • 1,823
  • 1
  • 15
  • 20