简体   繁体   中英

After Identity Custom User , User.Identity.GetUserId() returns wrong type as string

I created custom User model for entity framework and asp.net identity. I checked other answers in here, they are close to my question but answers not apply my requirement. so i am asking here.

Everything is ok. But when i try to get user id like :

 ApplicationUser user = await manager.FindByIdAsync(User.Identity.GetUserId());

User.Identity.GetUserId() return string. I configured it like Guid. But it returns string :(

My classes are here. Please help me, how can i get User.Identity.GetUserId() in a web api controller as Guid ?

public class GuidUserLogin : IdentityUserLogin<Guid>
    {
    }


    public class GuidUserRole : IdentityUserRole<Guid>
    {
    }

    public class GuidUserClaim : IdentityUserClaim<Guid>
    {
    }

    public class GuidRole : IdentityRole<Guid, GuidUserRole>
    {
    }

//public class GuidUserContext : IdentityDbContext<ApplicationUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> { }
    public class GuidUserStore : UserStore<ApplicationUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim>
    {
        public GuidUserStore(DbContext context)
            : base(context)
        {
        }
    }

    public class GuidRoleStore : RoleStore<GuidRole, Guid, GuidUserRole>
    {
        public GuidRoleStore(DbContext context)
            : base(context)
        {
        }
    }


    public class ApplicationUser : IdentityUser<Guid, GuidUserLogin, GuidUserRole, GuidUserClaim>, ICreateDateRequired
    {
        public ApplicationUser()
        {


        }

        [Key]
        public Guid UserId { get; set; }

        public override Guid Id { get; set; }

        public override string UserName { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }

        public string Password { get; set; }

        //Matching Attributes

        public override string Email { get; set; }
        public string FacebookId { get; set; }
        public string TwitterId { get; set; }
        public string GoogleId { get; set; }
        public override string PhoneNumber { get; set; }

        public string SocialAccessToken { get; set; }

        public string Gender { get; set; }

        public virtual List<Shade> Shades { get; set; }

        [InverseProperty("ParentUser")]
        public virtual List<UserFriendship> Friends { get; set; }

        public virtual List<Contact> Contacts { get; set; }

        //[Column(TypeName = "DateTime2")]
        //[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public DateTime? CreateDate { get; set; }

        public string ImageUrl { get; set; }
        public string ThumbUrl { get; set; }
        public string BackUrl { get; set; }

        public virtual List<ContactDetail> UserContactDetails { get; set; }
    }

The definition of GetUserId is this:

public static string GetUserId(this IIdentity identity);
public static T GetUserId<T>(this IIdentity identity) where T : IConvertible;

Unfortunately Guid is not an IConvertible and it will not return the Guid type in the Generic form. Therefore, we can not use: User.Identity.GetUserId()<Guid> as some people use User.Identity.GetUserId()<Int> when they change the ID to Int.

Therefore you should use Guid.Parse() or Guid.TryParse()

Guid.Parse(User.Identity.GetUserId())

@Erik method works fine, But As I did not wanted to override the original one, I added the following general extension:

 public static class ExtensionMethods
{
    public static Guid ToGuid(this string value)
    {
        Guid result= Guid.Empty;
        Guid.TryParse(value, out result);
        return result;          
    }
}

and then I used this:

User.Identity.GetUserId().ToGuid()

Edit: I came up with another solution:

I added an extension to the Identity object.

public static class IdentityExtensions
{
    public static Guid GetGuidUserId(this IIdentity identity)
    {
        Guid result = Guid.Empty;
        Guid.TryParse(identity.GetUserId(), out result);
        return result;
    }   
}

GetUserId() is actually the following extension method:

Microsoft.AspNet.Identity.IdentityExtensions.GetUserId(this IIdentity identity)

At some point there is no way to store a value as a Guid (cookies!). This means you'll have to manually change it (I just did this myself today). What I did was moved everything that uses Microsoft.AspNet.Identity , Microsoft.AspNet.Identity.Owin and Microsoft.Owin.Security into a separate directory. Then wrote my own Extension Class:

internal static class IIdentityExtensions
{
    public static Guid GetUserId(this IIdentity identity)
    {
        var result = Guid.Empty;

        string id = Microsoft.AspNet.Identity.IdentityExtensions.GetUserId(identity);

        Guid.TryParse(id, out result);

        return result;
    }

    public static string GetUserName(this IIdentity identity)
    {
        string result = Microsoft.AspNet.Identity.IdentityExtensions.GetUserName(identity);

        return result;
    }

    public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
    {
        string result = Microsoft.AspNet.Identity.IdentityExtensions.FindFirstValue(identity, claimType);

        return result;
    }
}

Just make sure you check for Guid.Empty (or change it to Guid?). You'll find that there are quite a few things that just accept string , and you'll have to convert them. For example:

namespace Microsoft.Owin.Security
{
  public static class AuthenticationManagerExtensions
  {
    public static ClaimsIdentity CreateTwoFactorRememberBrowserIdentity(
      this IAuthenticationManager manager, 
      string userId);
    public static Task<bool> TwoFactorBrowserRememberedAsync(
      this IAuthenticationManager manager, 
      string userId);
  }
}

So you'll have to .GetUserId().ToString() for certain methods to work.

For our project, I needed to abstract the key based on IUserKey (and store the identifier as a long within this interface).

The issue with the UserManager heavily reliant on strings was resolved (for me) by simply overriding the ToString() method in the concrete implementation of the user key object.

public class IdentityUserKey : IIdentityUserKey
{
    public long UserId { get; set; }

    public bool Equals(IIdentityUserKey other)
    {
        return other != null && other.UserId == UserId;
    }

    public override string ToString()
    {
        return UserId.ToString();
    }
}

In your case, perhaps you could have wrapped Guid in a similar interface, and then provided the necessary ToString() override as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM