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. openjdk8源码编译

    1. 安装源码管理工具 yum install mercurial 2. 下载源码 hg clone http://hg.openjdk.java.net/jdk8u/jdk8u jdk8u #执行源 ...

  2. Bootstrap学习(一):Bootstrap简介

    一.Bootstrap简介 Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更 ...

  3. python推导式创建序列

    推导式创建序列 推导式是一个或多个迭代器快速创建序列的一种方式.可以将循环和条件判断结合,简化代码.几个推导式注意符号的使用,比如小括号,方括号,大括号等等. 列表推导式 列表推导式生成列表对象,语法 ...

  4. UIImage 类说明

    + (UIImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle compatibleWithTraitCollection:( ...

  5. HBase篇(5)- BloomFilter

    [每日五分钟搞定大数据]系列,HBase第五篇.上一篇我们落下了Bloom Filter,这次我们来聊聊这个东西. Bloom Filter 是什么? 先简单的介绍下Bloom Filter(布隆过滤 ...

  6. 移动H5页面微信支付踩坑之旅(微信支付、单页面路由模拟、按钮加锁、轮询等常见功能)

    开发背景: .net混合开发的vue模板语法的单页面应用,所以不存在脚手架以及没有路由可以跳转. 项目描述: 需要写两个页面,在订单详情页需要点击“请输入手机号”进入手机号绑定页面,手机号绑定成功后自 ...

  7. 2017百度软研(C++)

    问了很多,不过很多也都没有问到,感觉有点偏,很深入的东西,越问越虚.第一次实习面试从百度开始,也从百度结束吧.看得见的差距,不想将就,所以还是拿最后一次机会去尝试.win or go home, 所以 ...

  8. BZOJ1969 航线规划

    给定一个无向图,每次删除一条边,求每次有多少关键边.一条边是关键边,当且仅当从1到n的所有路径都包含这条边.所有时刻图都联通. 考虑倒着做.相当于给一棵树,每次加一条边,这样树上这条边的两个端点间的路 ...

  9. Python-Django下载与基本命令

    1.下载Django: pip3 install django 2.创建一个django project django-admin.py startproject mysite 当前目录下会生成mys ...

  10. Highchartsjs使用总结及实时动态刷新图

    柱状图: $('#container').highcharts({ //突显红色柱: series: [ 523, 345, 785, 565, 843,{'color': 'red','y': 30 ...