When we apply the migration to an Asp Net Core Identity application, the system creates a set of basic Identity tables, where each table has its own columns. For example: the AspNetUsers table has its own set of columns, and it is possible to add new columns to that table.
Is it possible to remove columns?
If I don't want to use a particular column, is it possible to remove it?
Ofcouse you can.Take the AspNetUsers table as an example.
First:Create a new ApplicationUser
public class ApplicationUser:IdentityUser
{
//add a new colum
public string FullName { get; set; }
//remove a EmailConfirmed colum
[NotMapped]
public override bool EmailConfirmed { get; set; }
}
In your DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
In your startup(Change IdentityUser to ApplicationUser).
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
In your Views/Shared/_LoginPartial,change to
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
Then Migrate and generate database.
Test Result:You can see successfully add FullName and remove the EmailConfirmed colums.
For more details,you can see the doc.
Note:What you need to pay attention to is that many of these columns contain built-in methods of Identity. If you delete some of these columns, it may result in abnormal usage of Identity, so you need to be careful when deleting these columns.
Related
I'm trying to add a column to the identity (asp net core) RoleClaims table but I find content just to extend the roles and users classes and not to RoleClaims.
Could someone help with examples or point out content.
You would need to create a new class to extend the RoleClaim. Here is an example of how to do it if your key type is string:
public class ApplicationRoleClaim : IdentityRoleClaim<string>
{
public virtual ApplicationRole Role { get; set; }
}
You can add whatever new properties you want to this class then create a migration to add them as table columns.
You would also need to tell your IdentityDbContext to use this new class as well. Here is an example from the docs:
public class ApplicationDbContext
: IdentityDbContext<
ApplicationUser, ApplicationRole, string,
ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
ApplicationRoleClaim, ApplicationUserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
EDIT:
With your custom ApplicationRoleClaim class, you could override OnModelCreating as well. This is an example from the docs:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
⋮
modelBuilder.Entity<IdentityRoleClaim<string>>(b =>
{
b.ToTable("MyRoleClaims");
});
⋮
}
Reference: Identity model customization in ASP.NET Core
I made a demo with asp.net core 2.2 and it worked well ,try the following code , customize ApplicationRoleClaim to add other propertyies.
public class ApplicationRoleClaim: IdentityRoleClaim<string>
{
public string Description { get; set; }
}
Then use DbSet<TEntity> class which represents a collection for a given entity within the model and is the gateway to database operations against an entity to add the new column to table
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<ApplicationRoleClaim> ApplicationRoleClaim { get; set; }
}
Finally add-migration and update-database.
I've been working for quite a while on a production application using .NET Core 2.0 (originally 1.0) & EF Core.
This is a Code-First designed application, so all database changes have been made via Migrations.
Up until a recent deployment, Update-Database would make the changes correctly - however, recently it has been creating new schemas each time a model is added (instead of adding to the dbo schema like normal).
Example:
New Class Model: Test.cs
Table created in Database: DOMAIN\CurrentUser.Test
Any ideas on why this would be happening?
I suppose I can dig deep into the migrationBuilder to figure out how it is making Schema decisions, but seems like something simple must have changed to change the behavior.
"DOMAIN\CurrentUser" has dbo rights on the server in question.
For changing schema from EF Core, try to configure with builder.HasDefaultSchema("newschema"); or builder.Entity<User>().ToTable.
For changing the schema for all tables.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.HasDefaultSchema("newschema");
}
}
For chaning the schema for specific table.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>().ToTable("User", "newSchema");
}
}
I'm working with ASP.NET Core 2.0 and Identity Framework. My application has several subscriptions. Today, subscription Id is stored on the ApplicationUser Object and persisted to database context.
Every web call I'm looking at the database in order to get the subscriptionId property of the logged in user.
How can I avoid this database call for the logged in user?
as #Kirk said in the comments you can use claims for this.
You need to add subscriptionId to ClaimsIdentity when user is logging-in and retrieve the value in your controller.
I assume you have a subscriptionId property in ApplicationUser
public class ApplicationUser : IdentityUser
{
public int SubscriptionId { get; set; }
}
For adding custom claims you need to implement IUserClaimsPrincipalFactory
public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public CustomUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
ClaimsIdentity claimsIdentity = await base.GenerateClaimsAsync(user);
claimsIdentity.AddClaim(new Claim("subscription_id", user.SubscriptionId));
return claimsIdentity;
}
}
user.SubscriptionId must be a string. in other case you can create a property to cast the value to an string.
public string SubscriptionIdStting => SubscriptionId.ToString();
Register it to IServiceCollection
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>();
You can access SubscriptionId in Controller or Page like this :
User.FindFirst("subscription_id").Value
I have following tables:
Users, Groups, GroupUsers
I have my class like:
public class User
{
List<int> GroupIds;
}
I have a method in my Data Access Layer which returns a user after successful login with the list of all the group ids. How can I override or do something similar in identity to get information from that method?
I have searched the Internet a lot, watched YouTube tutorials, but no one is actually explaining it the way I need it. Can any one help?
First, use claims based security instead of role based: http://visualstudiomagazine.com/articles/2013/08/01/leveraging-claims-based-security-in-aspnet-45.aspx
I've also been retro-fitting an existing SQL based login system to work with identity management. Most of the work you're going to have to do lies within IdentityModel.cs. Specifically how you define ApplicationUser
public class ApplicationUser : IdentityUser<string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public async Task<ClaimsIdentity> 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;
}
}
I've overridden all 4 type parameters on the IdentityUser base class for my implementation, you may not need to do so, depends on how different your retrofit is from how Identity expects things to be.
The other main place you'll most likely have to customize things is within ApplicationDbContext where you'll have to set up where your user, group, and claims/role definitions reside with SQL.
I found these articles on typecastexception to be very useful:
http://typecastexception.com/post/2014/04/20/ASPNET-MVC-and-Identity-20-Understanding-the-Basics.aspx
http://typecastexception.com/post/2014/06/22/ASPNET-Identity-20-Customizing-Users-and-Roles.aspx
http://typecastexception.com/post/2014/04/20/ASPNET-Identity-20-Setting-Up-Account-Validation-and-Two-Factor-Authorization.aspx
http://typecastexception.com/post/2014/07/13/ASPNET-Identity-20-Extending-Identity-Models-and-Using-Integer-Keys-Instead-of-Strings.aspx
Overall there going to be a lot of trial and error in the process as you figure out what pieces of Identity you can utilize as is and where you need to plug in your own code.
Something else you may run into if your passwords aren't stored is having to provide your own implementation of PasswordHasher and plugging that in:
Asp.net Identity password hashing
I did' t get your question, if you want to override you have to mark the method virtual and inherit the class like this:
public class User
{
public virtual void YourMethod()
{
}
}
public class YourClass : User
{
public override void YourMethod()
{
}
}
If you want to separate the class to add some more mothods you can go like this:
partial class User
{
public static void YourMethod()
{
}
}
Create a UserInfo object
public class ApplicationUser : IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
}
public class UserInfo : ComparableEntity
{
public string Email { get; set; }
public string FullName { get; set; }
public string KidName { get; set; }
public string MobilePhone { get; set; }
}
Then create a database context
public class DatabaseContext : IdentityDbContext<ApplicationUser>, IDatabaseContext
{
public IDbSet<UserInfo> UserInfos { get; set; }
}
How can I integrate EF 5.0 with membership provider using code first?
I have my own database schema which I want to use for registration of users etc.
You should take a look at the SimpleMembershipProvider
It is very easy to use it together with EF.
Update
For MVC4 I would start with the blank template.
you need WebSecurity.InitializeDatabaseConnection to set up the database.
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "Id", "UserName", true);
It takes as parameters a name of a connectionstring, the table, a unique identifier column and the username-column.
The model I use for this piece of code above is:
[Table("Users")]
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string UserName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
To log someone in:
WebSecurity.Login(aUsername, aPassword);
The method above returns a bool, if it is true, login was successfull.
In the Web.config you do not need to define a membershipProvider as it was with default ASP.NET Membership.
If you need to gain access to the provider (to delete an account):
var provider = (SimpleMembershipProvider) Membership.Provider;
provider.DeleteAccount(aUsername); // Delete the account
provider.DeleteUser(aUsername, true); // delete the user and its data
For creating a new user (with my given model in this case)
WebSecurity.CreateUserAndAccount(aUsername, aPassword, new { Email = aEmail, FirstName = aFirstName, LastName = aLastName });
Benefit is, that you can now use your model for other EF classes as a foreign key without having the hassle when you want to do this with the normal asp.net membership. :-)
http://msdn.microsoft.com/en-us/library/f1kyba5e
This is actually nothing to do with EF.
EF is just a way to read data.
See also FORMS Authentication
http://support.microsoft.com/kb/301240?wa=wsignin1.0