如何在ASP.NET MVC中使用自定义属性扩展Identity?

时间:2016-06-12 20:51:41

标签: c# asp.net-mvc entity-framework asp.net-mvc-5 identity

我似乎与身份有仇恨/爱情关系。我喜欢它,因为它是大多数应用程序的完整解决方案。但我讨厌它,因为延伸并不是一件容易的事。我觉得它比它应该更加复杂。

我正在尝试向我的用户模型添加自定义属性和外键,但这似乎是一项非常困难的任务。

我需要添加一个名为Identity的新UserId字段,因为Id是一个字符串,将由数据库自动生成。然后,我需要将一个外键添加到Company模型,将另一个外键添加到Location模型。

我按照answer from this other question中的说明尝试添加两个新的外键,并能够从我的控制器中获取它们的值。

这是我到目前为止所做的。我做出修改后的ApplicationUser课程看起来像这样

public class ApplicationUser : IdentityUser
{
    [Key]
    public int MyUserId { get; set; }

    [ForeignKey("Company")]
    public int CompanyId { get; set; }

    [ForeignKey("Location")]
    public int CurrentLocationId { get; set; }

    public virtual Company Company { get; set; }

    public virtual Location Location { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here

        userIdentity.AddClaim(new Claim("MyUserId", this.MyUserId.ToString() ));

        userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString() ));

        userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString()));

        return userIdentity;
    }
}

我还创建了一个扩展类,允许我从控制器中获取值,如此

public static class IdentityExtensions
{
    public static int GetComapnyId(this IIdentity identity)
    {
        var claim = ((ClaimsIdentity)identity).FindFirst("ComapnyId");
        // Test for null to avoid issues during local testing
        return (claim != null) ? Int32.Parse(claim.Value) : 0;
    }

    public static int GetCurrentLocationId(this IIdentity identity)
    {
        var claim = ((ClaimsIdentity)identity).FindFirst("CurrentLocationId");
        // Test for null to avoid issues during local testing
        return (claim != null) ? Int32.Parse(claim.Value) : 0;
    }


    public static int GetMyUserId(this IIdentity identity)
    {
        var claim = ((ClaimsIdentity)identity).FindFirst("MyUserId");
        // Test for null to avoid issues during local testing
        return (claim != null) ? Int32.Parse(claim.Value) : 0;
    }

}

但是我遇到了下面列出的错误&#34;&#34;当我尝试添加新的迁移

这是错误

在模型生成期间检测到一个或多个验证错误:

  

ApplicationUser_Claims_Source_ApplicationUser_Claims_Target ::   参照的从属角色中的所有属性的类型   约束必须与相应的属性类型相同   主要角色。财产的类型&#39; MyUserId&#39;在实体上   &#39; IdentityUserClaim&#39;不符合财产的类型&#39; MyUserId&#39;上   实体&#39; ApplicationUser&#39;在引用约束中   &#39; ApplicationUser_Claims&#39 ;.   ApplicationUser_Logins_Source_ApplicationUser_Logins_Target ::   参照的从属角色中的所有属性的类型   约束必须与相应的属性类型相同   主要角色。财产的类型&#39; MyUserId&#39;在实体上   &#39; IdentityUserLogin&#39;不符合财产的类型&#39; MyUserId&#39;上   实体&#39; ApplicationUser&#39;在引用约束中   &#39; ApplicationUser_Logins&#39 ;.   ApplicationUser_Roles_Source_ApplicationUser_Roles_Target ::类型   参照约束的从属角色中的所有属性   必须与Principal中的相应属性类型相同   角色。财产的类型&#39; MyUserId&#39;实体&#39; IdentityUserRole&#39;不   不符合财产的类型&#39; MyUserId&#39;在实体&#39; ApplicationUser&#39;在   引用约束&#39; ApplicationUser_Roles&#39;。

这是我用来创建InitialCreate迁移

的命令
Add-Migration InitialCreate

如何添加外键并能够正确地从控制器获取外键?

1 个答案:

答案 0 :(得分:0)

Identity可以将主键(Id字段)更改为int。这是很多样板/空类,但它适用于我们。也许这会有所帮助?

public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    [ForeignKey("Company")]
    public int CompanyId { get; set; }

    [ForeignKey("Location")]
    public int CurrentLocationId { get; set; }

    public virtual Company Company { get; set; }

    public virtual Location Location { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here

        userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString() ));

        userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString()));

        return userIdentity;
    }
}

public class ApplicationUserLogin : IdentityUserLogin<int>
{
}

public class ApplicationUserRole : IdentityUserRole<int>
{
    [ForeignKey("RoleId")]
    public virtual ApplicationRole Role { get; set; }

    [ForeignKey("UserId")]
    public virtual ApplicationUser User { get; set; }
}

public class ApplicationRole : IdentityRole<int, UserRole>
{

}

public class ApplicationUserClaim : IdentityUserClaim<int>
{
}

然后我们还需要自定义ApplicationUserStore

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    public ApplicationUserStore(DbContext context)
        : base(context)
    {
    }
}