One of the first issues you will likely encounter when getting started with ASP.NET Identity centers on customizing the underlying data model. The Entity Framework provider uses Code-First to generate the data model and, initially, it may seem as if it is imposing its model upon your application. Fortunately, since the implementation of the provider uses Code-First, we can make significant customizations to the model and still take advantage of the features that ASP.NET Identity and EF provide.

In part one of this series, we will customize the ASP.NET Identity data model by simply changing the default schema and renaming the tables. In part two of this series, we will add audit fields to some of the tables and change the primary key data types from GUIDs to integers.

To get started, let’s generate the default data model to see what we are working with:

  1. Start by creating a new ASP.NET MVC and/or Web API project. Be sure the Authentication Mode is set to “Individual User Accounts” so the project template pulls in the required references, as well as the scaffolding for the default security model.
  2. Update the default connection string (“DefaultConnection”) in the web.config to point to your SQL Server database.
  3. Build and run the application.

Next, navigate to the login page and attempt to sign in with any credentials. Your login attempt will fail because no accounts are registered, but the Entity Framework should have generated the default data model for users, roles, and claims. If you check the database, you will find something similar to the following:

That is all well and good and if you have worked with the Membership Provider for .NET, you should be reasonably comfortable with what you see. However, we are interested in customizing the model; so let’s get started by renaming the tables and moving them into our application schema.

Step 1: Create the object model

To get started, add the following classes to your project. These classes form the object model that will be mapped to the data model. If you are following along in the attached sample project, you will find these classes under the NAM_Sample_Pt1.Models namespace.

ApplicationUserRole.cs

public class ApplicationUserRole : IdentityUserRole { }

ApplicationRole.cs

public class ApplicationRole : IdentityRole<string, applicationuserrole=""> { }

ApplicationUserClaim.cs

public class ApplicationUserClaim : IdentityUserClaim { }

ApplicationUserLogin.cs

public class ApplicationUserLogin : IdentityUserLogin { }

IdentityModels.cs

Update the ApplicationUser class with the following:

public class ApplicationUser : IdentityUser<string, applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">
{
    public async Task GenerateUserIdentityAsync(ApplicationUserManager 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
        return userIdentity;
    }

Step 2: Create the EF data context

Create a new security data context in IdentityModels.cs according to the following definition:

public class ApplicationDbContext : IdentityDbContext<applicationuser, applicationrole,="" string,="" applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">
{
    public ApplicationDbContext() : base("DefaultConnection") { }     public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

Note that the data context inherits from IdentityDbContext, which is the generic base data context that is included in the EF Provider for Identity. IdentityDbContext includes several generic type parameters, which should be set to the various types defined in the object model we created in the previous step.

We will revisit the data context once we have finished configuring the objects required to customize the model; however, be aware that this is where we will implement the fluent mapping.

Step 3: Create a custom user store

In ASP.NET Identity 2.0 user stores are the repositories for user data. The Entity Framework implementation of the user store requires a data context. Here is the implementation of our custom user store:

public class ApplicationUserStore :
    UserStore<applicationuser, applicationrole,="" string,="" applicationuserlogin,="" applicationuserrole,="" applicationuserclaim="">,
    IUserStore,
   IDisposable
{
    public ApplicationUserStore(ApplicationDbContext context) : base(context) { }
}

Step 4: Modify ApplicationUserManager to use the new object model

There are several lines in the ApplicationUserManager (included in the default project template) that must be modified. First, in the static Create() method, modify the creation of the ApplicationUserManager so that it takes an ApplicationUserStore and ApplicationDbContext as arguments in its constructor, as such:

        var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get()));

Step 5: Create the fluent mapping

We are finally ready to map our objects to our new data model. Begin by overriding OnModelCreating() in ApplicationDbContext . We will use EF Fluent API to map each of the five objects in our security object model to new tables in a new schema. The full fluent API mapping is included below:

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        {
            modelBuilder.HasDefaultSchema("NAM");             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserLogin");
                c.Properties(p => new
                {
                    p.UserId,
                    p.LoginProvider,
                    p.ProviderKey
                });
            }).HasKey(p => new { p.LoginProvider, p.ProviderKey, p.UserId });             // Mapping for ApiRole
            modelBuilder.Entity().Map(c =>
            {
                c.ToTable("Role");
                c.Property(p => p.Id).HasColumnName("RoleId");
                c.Properties(p => new
                {
                    p.Name
                });
            }).HasKey(p => p.Id);
            modelBuilder.Entity().HasMany(c => c.Users).WithRequired().HasForeignKey(c => c.RoleId);
            
            modelBuilder.Entity().Map(c =>
            {
                c.ToTable("User");
                c.Property(p => p.Id).HasColumnName("UserId");
                c.Properties(p => new
                {
                    p.AccessFailedCount,
                    p.Email,
                    p.EmailConfirmed,
                    p.PasswordHash,
                    p.PhoneNumber,
                    p.PhoneNumberConfirmed,
                    p.TwoFactorEnabled,
                    p.SecurityStamp,
                    p.LockoutEnabled,
                    p.LockoutEndDateUtc,
                    p.UserName
                });
            }).HasKey(c => c.Id);
            modelBuilder.Entity().HasMany(c => c.Logins).WithOptional().HasForeignKey(c => c.UserId);
            modelBuilder.Entity().HasMany(c => c.Claims).WithOptional().HasForeignKey(c => c.UserId);
            modelBuilder.Entity().HasMany(c => c.Roles).WithRequired().HasForeignKey(c => c.UserId);             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserRole");
                c.Properties(p => new
                {
                    p.UserId,
                    p.RoleId
                });
            })
            .HasKey(c => new { c.UserId, c.RoleId });             modelBuilder.Entity().Map(c =>
            {
                c.ToTable("UserClaim");
                c.Property(p => p.Id).HasColumnName("UserClaimId");
                c.Properties(p => new
                {
                    p.UserId,
                    p.ClaimValue,
                    p.ClaimType
                });
            }).HasKey(c => c.Id);
        }

You are now ready to build and run the project. As before, navigate to the login page and attempt to sign in, which will force the creation of the new data model. You should now see the model in the custom schema with the table names we declared in the fluent mapping.

In part two of this series we will add audit fields to some of the tables and change the primary key data types from GUIDs to integers.

 

Attachments

Web API 2 自定义默认Identity Table Name的更多相关文章

  1. Web API配置自定义路由

    默认访问Web API时,是无需指定method名.它会按照默认的路由来访问.如果你的Web API中出现有方法重载时,也许得配置自定义路由: 标记1为自定义路由,标记2为默认路由,需要把自定义路由排 ...

  2. Web API 基于ASP.NET Identity的Basic Authentication

    今天给大家分享在Web API下,如何利用ASP.NET Identity实现基本认证(Basic Authentication),在博客园子搜索了一圈Web API的基本认证,基本都是做的Forms ...

  3. 一张图说明 Web Api 参数绑定默认规则

    请求如下: 控制器如下: 慎重说明:不管请求方式是 get 还是 post , 简单类型的参数,如 name 和 id ,其值都是从 url 里面去取. Web API 从 url 还是 body 获 ...

  4. [Asp.Net web api]基于自定义Filter的安全认证

    摘要 对第三方开放的接口,处于安全的考虑需要对其进行安全认证,是否是合法的请求.目前在项目中也遇到这种情况,提供的接口因为涉及到客户铭感数据,所以在调用的时候,不能直接暴露,需要有一个认证的机制.所以 ...

  5. ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)

    GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...

  6. YbSoftwareFactory 代码生成插件【十三】:Web API 的安全性

    ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.Android设备.IOS等) ...

  7. ASP.NET MVC4中调用WEB API的四个方法

    http://tech.it168.com/a2012/0606/1357/000001357231_all.shtml [IT168技术]当今的软件开发中,设计软件的服务并将其通过网络对外发布,让各 ...

  8. Web API 的安全性

    Web API 的安全性 ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.An ...

  9. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

随机推荐

  1. [Micropython]TPYBoard v202 利用单片机快速实现家庭智能控制平台

    一提到智能家庭,大家可能首先想到的是各种大佬级公司搞的牛逼产品,或者说是创新产品.想想就觉得很复杂,有的用工控机,有的用树莓派,还有的用arduino,不管用什么,都绕不过服务器进行控制,比如yeel ...

  2. Luogu P3783 [SDOI2017]天才黑客

    题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...

  3. 扒一拔:Java 中的泛型(一)

    目录 1 泛型 1.1 为什么需要泛型 1.2 类型参数命名规约 2 泛型的简单实用 2.1 最基本最常用 2.2 简单泛型类 2.2.1 非泛型类 2.2.2 泛型类的定义 2.2.3 泛型类的使用 ...

  4. Python网络爬虫实战:根据天猫胸罩销售数据分析中国女性胸部大小分布

    本文实现一个非常有趣的项目,这个项目是关于胸罩销售数据分析的.是网络爬虫和数据分析的综合应用项目.本项目会从天猫抓取胸罩销售数据,并将这些数据保存到SQLite数据库中,然后对数据进行清洗,最后通过S ...

  5. Java和.NET(C#)的开发用到的技术对比总结

    前言 声明:我指的是一般的Java和.NET(C#)的后台开发用到的技术总结 最近一直在应聘ing,楼主的项目还是.NET(C#)项目居多,Java项目相对少,在这也吐槽下,招.NET(C#)的公司实 ...

  6. Jmeter实例(二)简单的性能测试场景

    我们在性能测试过程中,首先应该去设计测试场景,模拟真实业务发生的情境,然后针对这些场景去设计测试脚本.为了暴露出性能问题,要尽可能的去模拟被测对象可能存在瓶颈的测试场景. 我在本地部署了一个项目,可以 ...

  7. 网络编程-Socket介绍

    Socket介绍 什么是socket?(5分钟) Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议 ...

  8. 修改eclipce操作权限

    <dependencies> <dependency> <groupId>jdk.tools</groupId> <artifactId>j ...

  9. SQL not exist out join

    sql中exists,not exists的用法 - 飞翔-方向 积累 沉淀 - 博客园http://www.cnblogs.com/mytechblog/articles/2105785.html ...

  10. linux系统下MySQL表名区分大小写问题

    linux系统下MySQL表名区分大小写问题 https://www.cnblogs.com/jun1019/p/7073227.html [mysqld] lower_case_table_name ...