• 6 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 12/20/19

Authenticate With Entity Framework

Can the Database Be Customized?

You’ve just built a simple .NET Core web application and scaffolded Identity into it. As it stands, that application can authenticate users with Entity Framework. It doesn’t need anything else at all to complete that process. However, let’s look more closely at the database that has been created to store your user data and how you can personalize it and make it applicable to a specific application.

Run your application and register a new user. Then do the following:

  1. In Visual Studio, click the View menu and select SQL Server Object Explorer (SSOX). 

    Select SQL Server Object Explorer (SSOX) from the View menu.
  2. Under SQL Server in the SSOX, locate the local database, noted as (localdb)\MSSQLLocalDB.

  3. Expand the local database and the Databases folder within it.

  4. Find your project, then expand the Tables folder. 

    Expand the Tables folder within your project.
  5. Here you’ll see several tables that have been created for you by Identity and Entity Framework to drive your application. Each of these tables begins with the prefix AspNet. We’ll talk about what these are later, but for now, look at AspNetUsers. This table contains the individual user accounts you’ve registered. Right-click on AspNetUsers, and choose View Data from the pop-up menu. 

    Choose View Data
    Choose View Data

    When you select View Data from the pop-up menu, you see a window similar to the one shown here: 

    Data window showing the contents of the AspNet Users table.
    Data window

    This shows the contents of the AspNetUsers table. The user I registered using the email myclass@openclassrooms.com is displayed. This table, and all entries in it, are constructed by Entity Framework in conjunction with Identity to create secure user account management.

  6. Go back to the SQL Server Object Explorer again. Expand the AspNetUsers table, and then expand the Columns folder beneath it. 

    Expand the Columns folder
    Expand the Columns folder

    Here you see a list of all the column definitions in the AspNetUsers table. These are the standard properties for every user account created in this manner. But we mentioned something about personalizing these accounts, didn’t we?

Personalize User Data

Remember those two classes we scaffolded at the end of the last chapter? We said we’d get back to those later. Let's take a look at them now.

Add Personal Data to the User Class

Locate and click on Areas > Identity > Data, as shown below:

Areas > Identity > Data
Areas > Identity > Data

You’ll see those two classes here: MySecureAppDataContext and MySecureAppUser.

There’s nothing special about the data context class yet. It’s completely generic. We want to look at the  MySecureAppUser  class. Double-click on it to open it in the editor. Your file should look like this:

Your MySecureApp file open in the editor. Line 7 reads:
Class opened in the editor

Below is an accessible version of the code you should see in your file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace MySecureApp.Areas.Identity.Data
{
    // Add profile data for application users by adding properties to the MySecureAppUser class
    // 66 references
    public class MySecureAppUser : IdentityUser
    {
    }
}

Not much here, right? Just an empty class. The vital characteristic of this class is that it extends the IdentityUser class, which is the base class Identity and Entity Framework used to build that secure user accounts. So now, it’s time to start personalizing those accounts. You do that in this class, so let’s get started!

By default, your users don’t have any names. You don’t want them to be entirely anonymous, so go ahead and add properties for first and last names.

When you’re finished, your modified class should look something like this:

In the modified class, line 12 reads:
Modified class

Below is an accessible version of the code you should see in your file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace MySecureApp.Areas.Identity.Data
{
    // Add profile data for application users by adding properties to the MySecureAppUser class
    // 66 references
    public class MySecureAppUser : IdentityUser
    {
        // 0 references | 0 exceptions
        public string FirstName { get; set; }
        // 0 references | 0 exceptions
        public string LastName { get; set; }
        |
    }
}

Now go back and add the attribute [PersonalData] above each of these properties. 

The attribute [PersonalData] has been added above the two properties.
Add the attribute [PersonalData]

What exactly does adding the  [PersonalData]  attribute accomplish? Properties that you decorate with this attribute receive some special treatment. They are:

  • Deleted when the Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml Razor Page calls  UserManager.Delete.

  • Included in the downloaded data by the Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml Razor Page.

Modify Pages and Actions to Accommodate the New Data

First you need to update the  InputModel  class found in Areas/Identity/Pages/Account/Manage/Index.cshtml.cs

  1. Locate and open the file.

  2. Scroll down and find the  InputModel  class (about Line 41).

  3. Add properties to the model to match the first and last name properties you added to the user class. 

    Email and PhoneNumber properties have been added to the model.
    Add properties to the model

    Below is an accessible version of the code you should see in your file:

            public class Inputmodel
            {
                [Required]
                [EmailAddres]
                // 3 references | 0 exceptions
                public string Email { get; set; }
                
                [Phone]
                [Display(Name = "Phone number")]
                // 3 references | 0 exceptions
                public string PhoneNumber { get; set; }
                
                [Display(Name = "First name")]
                // 0 references | 0 exceptions
                public string FirstName { get; set; }
                
                [Display(Name= "Last name")]
                // 0 references | 0 exceptions
                public string LastName { get; set; }
            }
  4. Scroll down and locate where the  InputModel  class is populated with user data in the  OnGetAsync  method. Add the code to assign the values from the user class to the properties in the  InputModel  class. 

    Values have been assigned from the user class to the properties in the InputModel class: Email, PhoneNumber, FirstName, and LastName.
    Assign values

    Below is an accessible version of the code you should see in your file:

                var userName = await _userManager.GetUserNameAsync(user);
                var email = await _userManager.GetEmailAsync(user);
                var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
                
                Username = userName;
                
                Input = new InputModel
                {
                    Email = email,
                    PhoneNumber = phoneNumber
                    FirstName = user.FirstName,
                    LastName = user.LastName
                };
                
                IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);
                
                return Page();
            }    
  5. Now scroll down to the  OnPostAsync  method and find where the user object is retrieved from theUserManager (about Line 92).

  6. Add code here to assign the data values from the posted model to the corresponding properties in the user object. 

    From line 93: if (user == null) { return NotFound($
    Assign data values

    Below is an accessible version of the code you should see in your file:

                if (!ModelState.IsValid)
                {
                    return Page();
                }
                
                var user = await _userManager.GetUserAsync(User);
                if (user == null)
                {
                    return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
                }
                if (Input.FirstName != user.FirstName)
                {
                    user.FirstName = Input.FirstName;
                }
                if (Input.LastName != user.LastName)
                {
                    user.LastName = Input.LastName;
                }
  7. You need to make one more change. At the bottom of the method, right before the user’s login is refreshed, you need to update the user object. This is done with a call to the UserManager:  await _userManager.UpdateAsync(user);. Add this line as shown below:  

    From line 117: var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
    Call the UserManager

    Below is an accessible version of the code you should see in your file:

                var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
                if (Input.PhoneNumber != phoneNumber)
                {
                    var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
                    if (!setPhoneResult.Succeeded)
                    {
                        var userId = await _userManager.GetUserIdAsync(user);
                        throw new InvalidOperationException($"Unexpected error occurred setting phone number.");
                    }
                }
    
                await _userManager.UpdateAsync(user);
                
                await _signInManager.RefreshSignInAsync(user);
                StatusMessage = "Your profile has been updated";
                return RedirectToPage();

Next you need to add form elements to the pages that use the InputModel. Open the Areas/Identity/Pages/Account/Manage/Index.cshtml page and scroll down to the form group element that receives the user’s phone number (about Line 34). Insert the form elements into the form group as shown below: 

Insert the form elements into the form group
Insert the form elements into the form group

Below is an accessible version of the code you should see in your file:

            <div class="form-group">
                <label asp-for="Input.FirstName"></label>
                <input asp-for="Input.FirstName" class="form-control" />
                <label asp-for="Input.LastName"></label>
                <input asp-for="Input.LastName" class="form-control" />
                <label asp-for="Input.PhoneNumber"></label>
                <input asp-for="Input.PhoneNumber" class="form-control" />
                <span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
            </div>

Code Exercise: Update the Account/Register.cshtml page

You’ve just made the necessary modifications to the InputModel class and to the page at Areas/Identity/Pages/Account/Manage/Index.cshtml. Using what you’ve just learned, update the Register page and its input model to accept the two name fields you added to the user object.

Code Exercise: Update the Database and Test Your New Code

When you’ve completed the first exercise, open the Package Manager Console, and add a new migration by entering the following command in the console window:

Add-Migration CustomUserData

Then update the database:

Update-Database

When the update is complete, test your application.

  1. Register a new user.

  2. View your newly created user data on the /Identity/Account/Manage page.

  3. View the user’s personal data on the /Identity/Account/Manage/PersonalData page.

In the next section, we’ll explore how to use third-party external accounts to register and authenticate users.

Let’s Recap!

At this point, you have learned how to:

  1. Customize a user class to include additional personal data.

  2. Modify views and controllers to accommodate changes to user data models.

  3. Register and authenticate users in an MVC application with Entity Framework.

Now that you have a solid understanding of authentication using Entity Framework in an MVC application, let’s discuss how you can authenticate users using external accounts

Example of certificate of achievement
Example of certificate of achievement