Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

ASP.NET Core Identity Scaffolding

DZone's Guide to

ASP.NET Core Identity Scaffolding

In this blog post, we will look into how to override default views in ASP.NET Core Identity by using scaffolding. Ready... set... scaffold!

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

ASP.NET Core 2.1 introduces Razor UI class libraries that allow us to share UI artifacts with libraries and NuGet packages. One of the first official packages delivered with UI pieces is ASP.NET Core Identity. This blog post shows how to override default views of ASP.NET Core Identity by using scaffolding.

Let's start with ASP.NET Core 2.1 application that uses individual accounts for users.

ASP.NET Core Identity as Razor UI Library

When taking a look at project structure we see that there's no folder for identity-related views. This is because views are packaged to the ASP.NET Code Identity library. There's only the _ViewStart.cshtml file that applies the default layout page to all views in the identity area.

With ASP.NET Core Identity library we get default views and controllers. These things are packed to the library and we don't have any chance to make any modifications there. For example, we may want to add more fields to a user profile and want these fields to be filled when the user joins our site.

What we can do is override controllers and UI artifacts in ASP.NET Core Identity library and, for this, we can use ASP.NET Core Identity scaffolding.

For this, we right-click on the project, select Add and then New Scaffolded Item and Identity, as shown on the following screenshots.

When clicking on the Add button we can choose what artifacts we want to override.

And now comes a little surprise - although we have ASP.NET Core MVC application, we get, well...., overridden Razor pages.

I actually don't want it to be about Razor Pages but here we are and it's up to us to find also something good. Okay... pages at least have code-behind files and we don't have to mess with C# code written straight to Razor Pages.

Digging Around in Identity Libraries

Let's take a look at the code-behind file of the DownloadPersonalData page that was generated by the identity scaffolding.

public class DownloadPersonalDataModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly ILogger<DownloadPersonalDataModel> _logger;

    public DownloadPersonalDataModel(
        UserManager<IdentityUser> userManager,
        ILogger<DownloadPersonalDataModel> logger)
    {
        _userManager = userManager;
        _logger = logger;
    }

    public async Task<IActionResult> OnPostAsync()
    {
        var user = await _userManager.GetUserAsync(User);
        if (user == null)
        {
            return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
        }

        _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User));

        // Only include personal data for download
        var personalData = new Dictionary<string, string>();
        var personalDataProps = typeof(IdentityUser).GetProperties().Where(
                        prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute)));
        foreach (var p in personalDataProps)
        {
            personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null");
        }

        Response.Headers.Add("Content-Disposition", "attachment; filename=PersonalData.json");
        return new FileContentResult(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(personalData)), "text/json");
    }
}

Services are injected, that's nice. But the code-behind class inherits from PageModel and if we are scaffolding only in order to change something in a view, we suddenly have a new class that is overriding all future changes to the code-behind class of identity. Why are things like this? It's actually simple - for running web application views, which are actually compiled classes defined in the Microsoft.AspNetCore.Identity.UI.Views library. This is how the DownloadPersonalData page looks in the decompiler.

DownloadPersonalDataModel is defined in the Microsoft.AspNetCore.Identity.UI library and it is an internal class so we cannot use it from our projects.

As we can see, then, the pieces of code from those libraries are rendered pretty much useless for us and this is why we use scaffolding for overriding default views and code-behind classes.

Wrapping Up

ASP.NET Core Identity 2.1 comes with Razor UI libraries for identity-related views. If we are okay with default implementations then we can go with what comes included by default. If we want to change something related to identity UI we have to use identity scaffolding. Identity scaffolding creates us Razor pages with code-behind classes and we can make the changes we need. We cannot reuse views and models from identity libraries partially - we either use out-of-box ones or we override and get new ones. New ones are in no way related to those in identity UI libraries.

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
asp.net core ,ui ,web dev ,razor pages ,identity scaffolding

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}