После пользовательского идентификатора пользователя User.Identity.GetUserId() возвращает неверный тип в виде строки

Я создал пользовательскую модель пользователя для структуры сущностей и идентификации asp.net. Я проверил другие ответы здесь, они близки к моему вопросу, но ответы не соответствуют моему требованию. поэтому и спрашиваю здесь.

Все в порядке. Но когда я пытаюсь получить идентификатор пользователя, например:

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

User.Identity.GetUserId() возвращает строку. Я настроил его как Guid. Но он возвращает строку :(

Мои занятия здесь. Пожалуйста, помогите мне, как я могу получить User.Identity.GetUserId() в контроллере веб-API в качестве 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; }
    }

person Ras    schedule 13.05.2014    source источник


Ответы (3)


Определение 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>, так как некоторые используют User.Identity.GetUserId()<Int>, когда меняют ID на 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;
    }   
}
person Amir    schedule 04.01.2016

GetUserId() на самом деле является следующим методом расширения:

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

В какой-то момент нет возможности сохранить значение как Guid (куки!). Это означает, что вам придется изменить его вручную (я только что сделал это сам сегодня). Что я сделал, так это переместил все, что использует Microsoft.AspNet.Identity, Microsoft.AspNet.Identity.Owin и Microsoft.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() работать с определенными методами.

person Erik Philips    schedule 13.05.2014
comment
Но когда я пытаюсь получить идентификатор Guid в контроллере веб-API, он снова возвращает строку. var stringResult = IdentityExtensions.GetUserId (RequestContext.Principal.Identity); - person Ras; 13.05.2014
comment
Звучит как проблема с пространством имен, вы получаете неправильный метод расширения. - person Erik Philips; 13.05.2014
comment
Спасибо. Я исправил, как вы сказали. И теперь он выдает ошибку. Во время создания модели были обнаружены одна или несколько ошибок проверки: GuidUserStore: : EntityType 'GuidUserStore' не имеет определенного ключа. Определите ключ для этого EntityType. UserStores: EntityType: EntitySet «UserStores» основан на типе «GuidUserStore», для которого не определены ключи. - person Ras; 13.05.2014
comment
Когда я пытаюсь добавить идентификатор поля в GuidUserStore и создать плавную реализацию API, например modelBuilder.Entity‹GuidUserStore›().HasKey(x =› x.Id); затем выдает ошибку, когда я обновляю базу данных: значение не может быть нулевым. Имя параметра: набор сущностей - person Ras; 13.05.2014
comment
Я решил отменить пользовательский тип идентификатора Guid для использования с идентификатором. Я использую поле идентификатора строки asp.net как Guid().ToString(). Наконец, это работает. Спасибо за вашу поддержку - person Ras; 13.05.2014
comment
Если этот ответ решил ваш вопрос, примите ответ. - person Erik Philips; 19.05.2014

Для нашего проекта мне нужно было абстрагировать ключ на основе 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().

person Matt Beckman    schedule 10.04.2015