自定义 ASP.NET Identity Data Model with EF
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:
- 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.
- Update the default connection string (“DefaultConnection”) in the web.config to point to your SQL Server database.
- 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
自定义 ASP.NET Identity Data Model with EF的更多相关文章
- ASP.NET MVC - 安全、身份认证、角色授权和ASP.NET Identity
ASP.NET MVC - 安全.身份认证.角色授权和ASP.NET Identity ASP.NET MVC内置的认证特性 AuthorizeAttribute特性(System.Web.Mvc)( ...
- 【ASP.NET Identity系列教程(一)】ASP.NET Identity入门
注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...
- ASP.NET Identity 一 (转载)
来源:http://www.cnblogs.com/r01cn/p/5194257.html 注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的A ...
- ASP.NET Identity系列教程-2【Identity入门】
https://www.cnblogs.com/r01cn/p/5177708.html13 Identity入门 Identity is a new API from Microsoft to ma ...
- [转]Creating an Entity Framework Data Model for an ASP.NET MVC Application (1 of 10)
本文转自:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/creating-a ...
- 用于Simple.Data的ASP.NET Identity Provider
今天推举的这篇文章,本意不是要推举文章的内容,而是据此介绍一下Simple.Data这个很有意思的类ORM工具. 现在大家在.NET开发中如果需要进行数据访问,那么基本都会使用一些ORM工具,比如微软 ...
- 【分分钟内搭建一个带用户系统的博客程序(一)用户系统】asp.net core的Identity真香,EF真香!
不用不知道,一用香到爆. 老哥是个屌丝前端,但也想写点web应用耍一耍.之前弄过了NodeJs,也弄过JAVA,最近由于写游戏的原因用C#,索性上手一波asp.net core. 这篇博客记录的是,如 ...
- EF,ADO.NET Entity Data Model简要的笔记
1. 新建一个项目,添加一个ADO.NET Entity Data Model的文件,此文件会生成所有的数据对象模型,如果是用vs2012生的话,在.Designer.cs里会出现“// Defaul ...
- How to: Supply Initial Data for the Entity Framework Data Model 如何:为EF数据模型提供初始数据
After you have introduced a data model, you may need to have the application populate the database w ...
随机推荐
- c++中vector类的用法
概括:向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container).跟任意其它类型容器一样,它能够存放各种类型的对象.可以简单的认为,向量是一个能够存放任意类型的动态 ...
- .NET Core中延迟单例另一种写法【.NET Core和.NET Framework的beforefieldinit差异】
1.BeforeFieldInit是什么 前段时间在反编译代码时无意间看到在类中有一个BeforeFieldInit特性,处于好奇的心态查了查这个特性,发现这是一个关于字段初始化时间的特性[提前初始化 ...
- React-理解高阶组件
高阶组件:定义一个函数,传入一个组件,返回另外一个组件,另外一个组件包裹了传入的组件. 分类:属性代理高阶组件,反向继承高阶组件. 作用:代码复用,渲染节时. 高阶函数例子: function hel ...
- eclipse svn合并小结
合并时候,当前在哪个分支上,哪个分支即为“主干” 弱化主干 分支的概念.svn原则上并没有主干 分子 主 从的概念.从一个项目衍生(分支)出来的版本,都可以是主,也可以是从. 版本之间互相合并原理 文 ...
- Java性能优化之String字符串优化
字符串是软件开发中最重要的对象之一.通常,字符串对象在内存中是占据了最大的空间块,因此如何高效地处理字符串,必将是提高整体性能的关键所在. 1.字符串对象及其特点 Java中八大基本数据类型没有Str ...
- eclipse不能运行Struts2项目
刚接触Struts2项目,本想写个HelloWorld上手,谁知道光eclipse配置tomcat就鼓捣一晚上,查阅各种资料. 项目刚开始报错: "java.lang.ClassNotFou ...
- flask请求流程详解
先看一个流程图: 1.当一个请求进入的时候,Flask框架首先会实例化一个Request Context,封装了请求信息,保存在Request中.生成请求上下文后,Flask框架会将请求上下文推入到_ ...
- Django Rest framework基础使用之 serializer
rest-framework文档地址:http://www.django-rest-framework.org/ Django Rest framework是一个非常强大且灵活的工具包,用于构建web ...
- Python_%---format_43
fat39 博客园 首页 新随笔 联系 订阅 管理 随笔 - 142 文章 - 0 评论 - 0 python基础_格式化输出(%用法和format用法) 目录 %用法 format用法 %用 ...
- NFV论文集(二)
一 文章名称:VNF Placement with Replication for Load Balancing in NFV Networks 发表时间:2017 期刊来源:ICC: IEEE In ...