在自定义用户标识后,User.Identity.GetUserId()返回错误的字符串类型。

7

我为实体框架和ASP.NET Identity创建了自定义用户模型。

我查看了此处的其他答案,它们与我的问题接近,但答案不符合我的要求,因此我在这里询问。

一切都很好。但是当我尝试获取用户ID时:

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

User.Identity.GetUserId()返回字符串。尽管我将其配置为Guid,但它仍然返回字符串:(

我的类在这里。 请帮助我,如何在Web API控制器中获取User.Identity.GetUserId()并将其转换为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; }
    }
3个回答

11
GetUserId的定义如下:
public static string GetUserId(this IIdentity identity);
public static T GetUserId<T>(this IIdentity identity) where T : IConvertible;

遗憾的是,Guid不是IConvertible类型,因此它在泛型形式下不能返回Guid类型。因此,我们不能使用:User.Identity.GetUserId()<Guid>,当有些人将ID更改为Int时,他们使用User.Identity.GetUserId()<Int>

因此,您应该使用Guid.Parse()Guid.TryParse()

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

@Erik的方法很好,但是我不想覆盖原始方法,所以我添加了以下通用扩展:
 public static class ExtensionMethods
{
    public static Guid ToGuid(this string value)
    {
        Guid result= Guid.Empty;
        Guid.TryParse(value, out result);
        return result;          
    }
}

然后我使用了这个:

User.Identity.GetUserId().ToGuid()

编辑:我想到了另外一种解决方案:

我给Identity对象添加了一个扩展。

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

5

GetUserId() 实际上是以下扩展方法:

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

有时候无法将一个值存储为 Guid (例如cookies!)。这意味着您必须手动更改它(我今天刚刚这样做了)。 我所做的是将使用 Microsoft.AspNet.IdentityMicrosoft.AspNet.Identity.OwinMicrosoft.Owin.Security 的所有内容移动到单独的目录中。 然后编写自己的扩展类:

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;
    }
}

请确保检查Guid.Empty(或更改为Guid?)。您会发现有很多只接受string的事情,您需要将它们转换。例如:

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);
  }
}

因此,某些方法需要使用.GetUserId().ToString()才能正常工作。


但是当我在Web API控制器中尝试获取GUID ID时,它又返回字符串。var stringResult = IdentityExtensions.GetUserId(RequestContext.Principal.Identity); - Ras
似乎是命名空间问题,您正在获取错误的扩展方法。 - Erik Philips
谢谢。我按照你说的进行了修复,但现在出现了错误。在模型生成期间检测到一个或多个验证错误:GuidUserStore:EntityType 'GuidUserStore'未定义键。请为此EntityType定义键。 UserStores: EntityType: EntitySet 'UserStores'基于类型'GuidUserStore',该类型未定义键。 - Ras
当我尝试向GuidUserStore添加一个字段id并创建一个流畅的API实现,例如modelBuilder.Entity<GuidUserStore>().HasKey(x => x.Id);,然后在更新数据库时出现错误:值不能为空。参数名称:entitySet。 - Ras
我决定取消自定义的Guid类型,改用identity。我使用asp.net字符串id字段作为Guid().ToString()。最终,它起作用了。感谢您的支持。 - Ras
如果这个答案解决了你的问题,请接受答案 - Erik Philips

0
在我们的项目中,我需要根据 IUserKey 来抽象密钥(并将标识符存储为此接口内的 long)。 UserManager 高度依赖字符串的问题被解决了(对我来说),只需在用户密钥对象的具体实现中简单地覆盖 ToString() 方法即可。
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();
    }
}

在你的情况下,也许你可以将 Guid 包装在类似的接口中,然后提供必要的 ToString() 重写。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接