ASP.NET Core 2.1 Identity: How to remove the Default UI razor pages?
Asked Answered
M

4

30

Expanding the answer in this question: Change routing in ASP.NET Core Identity UI?

Javier recommends one of the following options when wanting to customise the URLs:

  • Use the scaffolding element of the Default UI and make all necessary customisations yourself.
  • Use a redirection rule that points the old routes to the new routes.
  • Don't use the Default UI at all.

From a new ASP.NET Core 2.1 MVC project, with Authentication: Individual User Accounts set, how do you NOT use the Default UI? It seems to be installed by default with Identity Core.

enter image description here

After the project is created, what is the method to remove the Default UI razor pages, and still use Identity Core?

Can I just delete the /Identity/ area, and create my own AccountController instead?

Magic answered 11/7, 2018 at 15:3 Comment(7)
If you want to change the UI the only thing you need to change is the views. Why do you want to change the controller?Tamica
I prefer to use my own route instead of /Identity/Account/, which appears not to be a recommended option using the UI.Magic
Again Why? "I prefer" may be the precursor to "it's broken" if you don't understand what it does. The question you linked to is only about the Identity UI package. It's used so you don't have to create/handle/manage the 50+ files used by the scaffolded UI. If you want to modify the UI, just don't use the package. You can generate the files with dotnet aspnet-codegenerator identity -dc WebApplication1.Data.ApplicationDbContext and modify them.Tamica
Check ASP.NET Core 2.1.0-preview1: Introducing Identity UI as a library. It explains what the Identity UI package does, why it was created and how to generate the razor pages so you can modify them.Tamica
Even better - Scaffold Identity in ASP.NET Core projects explains the tool's options. This could help you customize only the parts you wantTamica
It's more than just the route preference. I like MVC over these new Razor pages.Magic
You can use the --useDefaultUI parameter to generate and customize all the pages.Tamica
M
38

Using the article linked by Panagiotis Kanavos, I was able to reach a solution.

From the ASP.NET Core 2.1.0-preview1, there was a line .AddDefaultUI(), which you didn't have to include in Startup.cs.

services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultUI()
    .AddDefaultTokenProviders();

In the final release version of Core 2.1 however, the same section was simplified to:

services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

The solution, if you change AddDefaultIdentity back to AddIdentity, you can override the defaults. I.E. don't include .AddDefaultUI() (and also don't scaffold the UI) and you can write your own.

services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    // .AddDefaultUI()
    .AddDefaultTokenProviders();

Then, I think it's safe to delete the /Areas/Identity/ folder, but I'm not 100%

Update:

I cleaned up my answer to detail the final solution I ended up going with, to remove the default identity UI razor pages that come with ASP.NET Core 2.1 and and use MVC instead.

1) In Startup.cs,

    public void ConfigureServices(IServiceCollection services)
    {
        // Unrelated stuff commented out...

        // BEGIN: Identity Setup (Overrides default identity)
        services.AddIdentity<ApplicationUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
        // END: Identity Setup

        services.Configure<IdentityOptions>(options =>
        {
            // Set your identity Settings here (password length, etc.)
        });

        // More unrelated stuff commented out...

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // Added after AddMvc()
        services.ConfigureApplicationCookie(options =>
        {
            options.LoginPath = $"/account/login";
            options.LogoutPath = $"/account/logout";
            options.AccessDeniedPath = $"/account/access-denied";
        });

        // More unrelated stuff commented out...
    }

And obviously, replace both ApplicationUser, and IdentityRole with your own classes if required.

2) Delete the Area folder for Identity that came default with your ASP.NET Core 2.1 project.

3) Create a new separate ASP.NET Core 2.0 project (not "2.1"), with Individual User Account authentication selected in the project creation window.

4) Copy the AccountController and ManageController, with the corresponding ViewModels and Views, from the 2.0 project to your ASP.NET Core 2.1 project.

Doing the above, I haven't run into any issues so far.

Magic answered 11/7, 2018 at 15:43 Comment(2)
You'll probably want to configure the default EmailService as well; services.AddSingleton<IEmailService, EmailService>()Adverb
I find it bizarre that the project templates don't give you an option to choose the old controller style when you're creating an Angular application, or any API based application for that matter. The client is POSTing data regardless so there's less benefit (that I can see) in almost forcing a developer to either use RazorPages and override unnecessarily, or spend time ripping out the new and refitting the old. Aren't project templates supposed to help us?Sandberg
S
5

A little late, but there is a much easier way to do it. You can add new scaffolding to override everything. Check out this article.

Stairwell answered 31/8, 2018 at 16:34 Comment(0)
T
3

I upvoted the first answer because it got me 90 percent there, wanted to give out the rest (it was a little too long to put in the comments). So you'll want to keep that /Areas/Identity/ folder because it points to your shared folder if you happen to be using the header from the default template, if not it doesn't matter, delete it. The backend will still point to Identity/Account/Register/, so create a controller called Account make a folder in views called Account and put the Register.cshtml. I took the original html from a debugger window that you can use as a template to customize. Put inside Register.cshtml:

<div class="container body-content">


<h2>Register</h2>

<div class="row">
    <div class="col-md-4">
        <form method="post" action="/Identity/Account/Register" novalidate="novalidate">
            <h4>Create a new account.</h4>
            <hr>
            <div class="text-danger validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
            <div class="form-group">
                <label for="Input_Email">Email</label>
                <input class="form-control" type="email" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Input_Email" name="Input.Email" value="">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.Email" data-valmsg-replace="true"></span>
            </div>
            <div class="form-group">
                <label for="Input_Password">Password</label>
                <input class="form-control" type="password" data-val="true" data-val-length="The Password must be at least 6 and at max 100 characters long." data-val-length-max="100" data-val-length-min="6" data-val-required="The Password field is required." id="Input_Password" name="Input.Password">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.Password" data-valmsg-replace="true"></span>
            </div>
            <div class="form-group">
                <label for="Input_ConfirmPassword">Confirm password</label>
                <input class="form-control" type="password" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="Input_ConfirmPassword" name="Input.ConfirmPassword">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.ConfirmPassword" data-valmsg-replace="true"></span>
            </div>
            <button type="submit" class="btn btn-default">Register</button>
        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8IWbPHM_NTJDv_7HGewWzbbRveP09yQOznYdTWL2aN5X_4_eVbNE1w8D_qz7zegloVtdAhuVOJbJLQo0ja73FB3PgYycyGpn-DfX3fJqv4Cx8ns6Ygh6M7nMxV0eozO7hoDxUfPwrIJb2RcFtyzhPpMevZ4P0M8aVyBP55SP-5C4l23dCtDXXUOAY_YLwt67dw"></form>
    </div>
</div>


        <hr>
        <footer>
            <p>© 2018 - SqlServerApp</p>
        </footer>
    </div> 

Like the other answer says, alter Startup:

services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    // .AddDefaultUI()
    .AddDefaultTokenProviders();

Also gotta make the route to your controller, same Startup.cs file, keep the other route that's in there, probably keep it first now that I think about it, since it checks them sequentially:

app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "identity",
                template: "Identity/{controller=Account}/{action=Register}/{id?}");
Tripod answered 11/7, 2018 at 23:52 Comment(0)
N
1

Maybe this is sufficient solution - don't let user access the Identity pages:

//program.cs

app.Use(async (context, next) =>
{
    await next();
    if (context.Request.Path.StartsWithSegments("/Identity"))
    {
        context.Response.Redirect("/");// redirect to index
        return;
    }
});
Necessitous answered 20/8, 2022 at 11:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.