How to Add Custom Properties to the User Entity

Note: If your application is less than version 4.4.x, please follow this article.

Introduction

In this step-by-step article, I will explain how you can customize the user entity class, which is available in every web application you create using the ABP framework, according to your needs. When you read this article, you will learn how to override the services of built-in modules, extend the entities, extend data transfer objects and customize the user interface in the applications you develop using the ABP framework.

Note: This article is not about customizing the Login page. If you have such a need, please follow this article.

You can see the screenshots below which we will reach at the end of the article.

custom-identity-user-list

new-user

Preparing the Project

Startup template and the initial run

Abp Framework offers startup templates to get into the work faster. We can create a new startup template using Abp CLI:

abp new CustomizeUserDemo

In this article, I will go through the MVC application, but it will work also in the Angular, Blazor Server, and Blazor WebAssembly application.

After the download is finished, we can run CustomizeUserDemo.DbMigrator project to create the database migrations and seed the initial data (admin user, role, etc). Then we can run CustomizeUserDemo.Web to see that our application is working.

Default admin username is admin and password is 1q2w3E*

initial-project

In this article, we will go through a scenario together and find the solutions to our questions through this scenario. However, since the scenario is not a real-life scenario, it may be strange, please don't get too about this issue :)

Step-1

Create the Users folder in the CustomizeUserDemo.Domain.Shared project, create the class UserConsts inside the folder and update the class you created as below:

public static class UserConsts
{
    public const string TitlePropertyName = "Title";

    public const string ReputationPropertyName = "Reputation";

    public const int MaxTitleLength = 64;

    public const double MaxReputationValue = 1_000;

    public const double MinReputationValue = 1;
}

Step-2

Update the CustomizeUserDemoEfCoreEntityExtensionMappings class in the CustomizeUserDemo.EntityFramework project in the EntityFrameworkCore folder as below:

public static class CustomizeUserDemoEfCoreEntityExtensionMappings
{
    private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();

    public static void Configure()
    {
        CustomizeUserDemoGlobalFeatureConfigurator.Configure();
        CustomizeUserDemoModuleExtensionConfigurator.Configure();

        OneTimeRunner.Run(() =>
        {
            ObjectExtensionManager.Instance
                .MapEfCoreProperty<IdentityUser, string>(
                    UserConsts.TitlePropertyName,
                    (_, propertyBuilder) =>
                    {
                        propertyBuilder.HasDefaultValue("");
                        propertyBuilder.HasMaxLength(UserConsts.MaxTitleLength);
                    }
                ).MapEfCoreProperty<IdentityUser, int>(
                    UserConsts.ReputationPropertyName,
                    (_, propertyBuilder) =>
                    {
                        propertyBuilder.HasDefaultValue(UserConsts.MinReputationValue);
                    }
                );
        });
    }
}

This class can be used to map these extra properties to table fields in the database. Please read this article to improve your understanding of what we are doing.

So far, we have added our extra features to the User entity and matched these features with the ef core.

Now we need to add migration to see what has changed in our database. This for, open the Package Manager Console (PMC) under the menu Tools > NuGet Package Manager.

nuget-package-manager

Select the CustomizeUserDemo.EntityFramework as the default project and execute the following command:

Add-Migration "Updated-User-Entity"

added-new-migration

This will create a new migration class inside the Migrations folder of the CustomizeUserDemo.EntityFrameworkCore project.

If you are using another IDE than the Visual Studio, you can use dotnet-ef tool as documented here.

Finally, run the CustomizeUserDemo.DbMigrator project to update the database.

When we updated the database, you can see that the Title and Reputation columns are added to the Users table.

user-table

Step-3

Open the CustomizeUserDemoModuleExtensionConfigurator in the CustomizeUserDemo.Domain.Shared project, and change the contents of the ConfigureExtraProperties method as shown below:

private static void ConfigureExtraProperties()
{
    ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity =>
    {
        identity.ConfigureUser(user =>
        {
            user.AddOrUpdateProperty<string>(
                UserConsts.TitlePropertyName,
                options =>
                {
                    options.Attributes.Add(new RequiredAttribute());
                    options.Attributes.Add(
                        new StringLengthAttribute(UserConsts.MaxTitleLength)
                    );
                }
            );
            user.AddOrUpdateProperty<int>(
                UserConsts.ReputationPropertyName,
                options =>
                {
                    options.DefaultValue = UserConsts.MinReputationValue;
                    options.Attributes.Add(
                        new RangeAttribute(UserConsts.MinReputationValue, UserConsts.MaxReputationValue)
                    );
                }
            );
        });
    });
}

That's it. Now let's run the application and look at the Identity user page. You can also try to edit and recreate a record if you want, it will work even though we haven't done anything extra. Here is the magic code behind ABP framework.

If there is a situation you want to add, you can click the contribute button or make a comment. Also, if you like the article, don't forget to share it :)

Happy coding :)

extending-entities
washyn 86 weeks ago

great

jeffahn 84 weeks ago

Thank you for the article. Is it possible to add a dropdown to user Add/Edit dialog box? I am trying to add "Organization Unit" dropdown to user Add/Edit dialog box.

Berkan Şaşmaz 83 weeks ago

Yes you can with(or without) module entity extension system. ABP's module entity extension system support adding an extension property to an entity that is Id of another entity (foreign key).


See: https://docs.abp.io/en/abp/latest/Module-Entity-Extensions#navigation-properties-foreign-keys

1
jeffahn 83 weeks ago

I feel stupid. I thought I read everything in the documents. Thank you Berkan! I will try the extension system.

1 1 1
coolmoshen 73 weeks ago

Hello, how can the title and reputation fields be filtered through search?

Berkan Şaşmaz 73 weeks ago

Hello, you may need to override the corresponding method for this. Then you can query this custom property. https://github.com/abpframework/abp/issues/10662#issuecomment-972765041

coolmoshen 72 weeks ago

Thank you. I have studied this issue carefully.

To add the title and reputation fields in advanced search, I need to create a new EfCoreRepository<IIdentityDbContext, IdentityUser, Guid>, right? Because EfCoreIdentityUserRepository.GetListAsync cannot pass title and reputation.

Berkan Şaşmaz 72 weeks ago

Yes, you need to override the corresponding GetListAsync method to do what you want. Then you can edit the query.

fxandrei 59 weeks ago

How would you go about customizing the use registration entity and its related page ?

Berkan Şaşmaz 57 weeks ago

ABP already has detailed documentation on these topics. That's why I don't want to add them to this article. But I may try something to show how easy this is in another article in the future.

See: https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide

Kadir İlhan 57 weeks ago

great, very good. thanks.

Adrian Inman 42 weeks ago

This is really useful... but... I don't believe it covers how to programmatically access these fields in the code... it relies on the framework to pipe them into the UI... I need to be able to read custom properties added in back out via the CurrentUser or by using that to obtain the IdentityUser object related to this... neither of these have the additional properties configured through the extension system when I look... where would I find these?

Berkan Şaşmaz 41 weeks ago

Hi, this article basically uses ABP's object extensions system. I can recommend you to read this document to access the extra properties you added. Also, if you are wondering how to query the database with the related extra property field, you can check it here.

JiaQing Liu 32 weeks ago

Hi, I'm using File Management Module to get Upload and Add to Database methods in another page and I am also using Extra Properties to add DocId and Url properties to FMFileDescriptor table. How can I use the .razor page to assign the Id of the currently open page to the DocId property and the page path to the Url on the page I'm using? And when I run ExtrProperties also doesn't work. It is always empty extraProperties: {}

More from Berkan Şaşmaz