39

I'm using asp.net Identity 2.0 for users to log into my website, where the authentication details are stored in an SQL database. Asp.net Identity has been implemented in a standard way as can be found in many online tutorials.

The ApplicationUser class in IdentityModels has been extended to include a custom property:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    {
       CookieAuthenticationOptions.AuthenticationType
       var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
       return userIdentity;
    }
    //My extended property
    public string Code { get; set; }
}

When I register a new user I pass the Code custom property in the RegisterBindingModel but I'm not sure how to insert this custom property to the WebUsers table.

I did as bellow but it doesn't actually inserting this property to the table together with the username and password.

var user = new ApplicationUser() { UserName = userName, Email = model.Email, Code=model.Code };

And the entire function:

[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var userName = !string.IsNullOrEmpty(model.UserName) ? model.UserName : model.Email;
        //I set it here but it doesn't get inserted to the table.
        var user = new ApplicationUser() { UserName = userName, Email = model.Email, Code=model.Code };

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);

        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        return Ok();
    }

What am I missing? I was looking at similar questions but couldn't find an answer for this.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
user3378165
  • 6,546
  • 17
  • 62
  • 101
  • I think your code is OK, are you sure that the `Code` property is being filled in the `model` parameter? – jumuro Nov 11 '16 at 11:37
  • Yes I'm sure, I checked it. But when I check the table in the database, the new user comes up but the code field is always `null`. – user3378165 Nov 11 '16 at 13:26
  • How is the UserManager defined? Have a look at https://github.com/tjoudeh/AspNetIdentity.WebApi – Sir Rufo Nov 13 '16 at 20:44
  • Probably you are sure that you followed all steps to add property to user correctly, anyway I shared all steps with descriptions. Give it a try, I added `Code` field successfully by following these steps ↓ – Reza Aghaei Nov 13 '16 at 22:19

3 Answers3

75

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:

  1. Create an ASP.NET Web Application
  2. Make sure you select MVC and the Authentication is Individual User Accounts
  3. Go to Models folder → Open IdentityModels.csApplicationUser class and add the property:

    public string Code { get; set; }
    
  4. Build the project
  5. Go to TOOLS menu → Nuget Package Manager → click Package Manager Console
  6. 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.
    
  7. 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.
    
  8. 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 the Code 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.

  9. 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; }
    
  10. 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>
    
  11. 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 };
    
  12. 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:

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?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Thank you for the clear and detailed answer, the only one step that I'm missing is: #9: "Go to Models folder → Open `AccountViewModels.cs` file → `RegisterViewModel` class ", on my `AccountViewModels.cs` file there is no a `RegisterViewModel` class, should I add it? Thank you! – user3378165 Nov 14 '16 at 16:41
  • You're welcome. You will need it. If you don't need, there will not be a `Code` in passed model from View. – Reza Aghaei Nov 14 '16 at 17:45
  • Follow instructions in a clean solution and it will be clear for you what you are doing. – Reza Aghaei Nov 14 '16 at 17:46
  • I'm not passing the `Code` from the `View`. I'm calling the API from a totally different project. – user3378165 Nov 14 '16 at 18:21
  • When I register through the Register View I don't pass it as a parameter. What could be the issue? Thank you very much for your help! – user3378165 Nov 14 '16 at 18:45
  • See the signature of action: `public async Task Register(RegisterBindingModel model)` and your code in the action `var user = new ApplicationUser() { UserName = userName, Email = model.Email, Code=model.Code };` It means you have created `Code` in `RegisterBindingModel` class, so you should pass the code value to the action. You may pass the value using `View` or by sending an ajax request. Anyway you should feed the action username, email and code somehow. – Reza Aghaei Nov 14 '16 at 20:11
  • Thank you, I- by mistake called the wrong function... I created another Registration function with the `Code` parameter but I forgot to call the new Register function so it was always empty.. I didn't had to change my code at all just to fix the API call.. I accepted the answer since it's an excellent answer and it will hopefully help others. Thank you so much! – user3378165 Nov 14 '16 at 20:46
  • You're welcome and thank you for your kind response :) – Reza Aghaei Nov 14 '16 at 20:49
  • @RezaAghaei do you know how to make this custom property (in this example code property) or another one unique in the registration proccess in order not to have duplicates? pretty much like email. – GeralexGR May 27 '17 at 15:07
  • This is a great guide. But where does this get registered? Say I have a database with the extra fields, and my identityUser has gotten the same extra fields. On user create it won't put in those values until I update something. But what? – LaughingMan Dec 20 '17 at 23:51
  • @LaughingMan Take a look at Step 10 and 11. – Reza Aghaei Dec 21 '17 at 01:54
  • @RezaAghaei Thanks man, exactly what I was looking for. Much appreciated. – FreedomOfSpeech Aug 28 '18 at 20:14
12

Hope this might help others, since the original post is 1+years old

If have already created the project with 'Authentication Individual User Accounts:

In Solution Explorer go to project>Models>IdentityModels.cs

under public class ApplicationUser: IdentityUser (should be the first class).

Add your custom properties after public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) like my example below:

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;
    }
    **//add custom properties here - these are just examples**
    public bool SendEmails { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Then using NuGet Packagemanager:

  • enable-migrations (if you haven't already)
  • add-migration [enter]
  • nameYourMigration [enter]
  • (view the migration file to verify your properties are going to be added)
  • update-database [enter]
  • Check your AspNetUsers db table to be sure the properties were added correctly

I hope this helps..

Ben-Carpenter
  • 189
  • 1
  • 6
1

I think the main problem still is you don't register the new claims at the ApplicationUser class.

I was having the same problem and I solved it with a few lines after the CreateIdentityAsync.

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
    {
       CookieAuthenticationOptions.AuthenticationType
       var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);

       // Add custom user claims here
        userIdentity.AddClaim(new Claim("Code",this.Code));
       return userIdentity;
    }
    //My extended property
    public string Code { get; set; }
}