How to extend IdentityUser with custom property
If you follow all steps of adding a custom field to user, you will finish the tasks successfully.
Here is all steps to add a custom field to user:
- Create an ASP.NET Web Application
- Make sure you select MVC and the Authentication is Individual User Accounts
Go to Models folder → Open IdentityModels.cs → ApplicationUser class and add the property:
public string Code { get; set; }
- Build the project
- Go to TOOLS menu → Nuget Package Manager → click Package Manager Console
Type
Enable-Migrations
and press Enter and wait until the task get completed. You will see a response which says:Checking if the context targets an existing database...
Code First Migrations enabled for project WebApplication1.Type
Add-Migration "Code"
and press Enter and wait until the task get completed. You will see a response which says:Scaffolding migration 'Code'. The Designer Code for this migration
file includes a snapshot of your current Code First model. This
snapshot is used to calculate the changes to your model when you
scaffold the next migration. If you make additional changes to your
model that you want to include in this migration, then you can
re-scaffold it by running 'Add-Migration Code' again.Type
Update-Database
and press Enter and wait until the task get completed. You will see a response which says:Specify the '-Verbose' flag to view the SQL statements being applied
to the target database.
Applying explicit migrations: [201611132135242_Code].
Applying explicit migration: 201611132135242_Code.
Running Seed method.At this step if you refresh SQL Server Object Explorer and go to database and see tables, under
dbo.AspNetUsers
under columns, you will see theCode
field. If you didn't know which database or even which server you should look for, open Web.Config file and take a look at connection string which is something like this:<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-WebApplication1-20161114125903.mdf;Initial Catalog=aspnet-WebApplication1-20161114125903;Integrated Security=True"
providerName="System.Data.SqlClient" />You can see data source (which is sql server instance) and something .mdf which is database name.
Go to Models folder → Open AccountViewModels.cs file → RegisterViewModel class and add this property:
(In APIv2 with EF6, you can add the below line in Models folder → AccountBindingModels file → RegisterBindingModel class)public string Code { get; set; }
Go to Views folder → Account folder → Open Register.cshtml file and add this code near other fields, for example below password:
<div class="form-group">
@Html.LabelFor(m => m.Code, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.Code, new { @class = "form-control" })
</div>
</div>Go to Controllers folder → Open AccountController.cs file → in http post Register action, change the line which creates user to this:
var user = new ApplicationUser { UserName = model.Email, Email = model.Email,
Code= model.Code };Run project and go to
/Account/Register
url and register a new user. After registering the user, if you go to database again and View Data of dbo.AspNetUsers table, you will see the code has been saved.
Download
You can clone or download a working example here:
- r-aghaei/AddPropertyToIdentityUserExample
Further reading - How to Add a custom Property to IdentityRole?
If you are interested to know how to add a new property to IdentityRole
, take a look at How to Add a custom Property to IdentityRole?
Add custom unique property to my IdentityUser
In EF core, you could specify that an index should be unique, meaning that no two entities can have the same value(s) for the given property(s).
Add below code in your dbContext OnModelCreating
and add migrations.
modelBuilder.Entity<ApplicationUser>()
.HasIndex(b => b.CustomProperty)
.IsUnique();
Refer to https://learn.microsoft.com/en-us/ef/core/modeling/indexes
Implement get/set methods for Identity User custom property
You need to create scope of identity, just create your identity and add scoped
services.AddScoped<IUserIdentity, UserIdentity>();
You need to implement middleware
for map all your properties in identity.
Add to startup:
app.UseMiddleware<UserIdentityAccessor>();
Implementation:
public class UserIdentityAccessor
{
private readonly RequestDelegate _next;
public UserIdentityAccessor(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context, IUserIdentity userIdentity)
{
var user = (ClaimsIdentity) context.User.Identity;
if (user.IsAuthenticated)
{
var first = user.FindFirst(ClaimsName.FirstName).Value; \\ get info from claims
userIdentity.FirstName = first; \\ and add to identity
}
else
{
userIdentity.FirstName = null;
}
await _next(context);
}
}
And now you can get identity wherever you want
How to extend available properties of User.Identity
Whenever you want to extend the properties of User.Identity with any additional properties like the question above, add these properties to the ApplicationUser class first like so:
public class ApplicationUser : IdentityUser
{
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
return userIdentity;
}
// Your Extended Properties
public long? OrganizationId { get; set; }
}
Then what you need is to create an extension method like so (I create mine in an new Extensions folder):
namespace App.Extensions
{
public static class IdentityExtensions
{
public static string GetOrganizationId(this IIdentity identity)
{
var claim = ((ClaimsIdentity)identity).FindFirst("OrganizationId");
// Test for null to avoid issues during local testing
return (claim != null) ? claim.Value : string.Empty;
}
}
}
When you create the Identity in the ApplicationUser class, just add the Claim -> OrganizationId like so:
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 => this.OrganizationId is a value stored in database against the user
userIdentity.AddClaim(new Claim("OrganizationId", this.OrganizationId.ToString()));
return userIdentity;
}
Once you added the claim and have your extension method in place, to make it available as a property on your User.Identity, add a using statement on the page/file you want to access it:
in my case: using App.Extensions;
within a Controller and @using. App.Extensions
withing a .cshtml View file.
EDIT:
What you can also do to avoid adding a using statement in every View is to go to the Views folder, and locate the Web.config file in there.
Now look for the <namespaces>
tag and add your extension namespace there like so:
<add namespace="App.Extensions" />
Save your file and you're done. Now every View will know of your extensions.
You can access the Extension Method:
var orgId = User.Identity.GetOrganizationId();
insert IdentityUser with default values and custom properties fails
thanks to tieson
i was able to fix this using this technique:
http://www.vannevel.net/2015/04/03/how-to-configure-a-custom-identityuser-for-entity-framework/
with a basis in the following:
- SQL column default value with Entity Framework
- https://www.learnentityframeworkcore.com/configuration/data-annotation-attributes/databasegenerated-attribute
so in the end my code looked like:
public class ApplicationUser : IdentityUser
{
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int companyId { 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()));
return userIdentity;
}
}
hope this helps someone else
How To show custom Properties on an IdentityUser List using MVC 5?
Change this:
@model IEnumerable<Microsoft.AspNet.Identity.EntityFramework.IdentityUser>
To this:
@model IEnumerable<YourNamespace.ApplicationUser>
Related Topics
Convert from Scientific Notation String to Float in C#
Insert into C# with SQLcommand
When a Class Is Inherited from List<>, Xmlserializer Doesn't Serialize Other Attributes
Winforms Radiobuttonlist Doesn't Exist
Resharper Warning - Access to Modified Closure
Determining If File Exists Using C# and Resolving Unc Path
Creating Diagonal Pattern in Wpf
Checking File/Folder Access Permission
How to Pass Values Between Forms in C# Windows Application
C# Split String and Remove Empty String
Static Binding Doesn't Update When Resource Changes
Camera.Main Is Null When Performing Raycast