Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identity (not msidentity) scaffolding doens't work with InteractiveServer render mode on Blazor server #2738

Open
tommyvct opened this issue May 9, 2024 · 0 comments

Comments

@tommyvct
Copy link

tommyvct commented May 9, 2024

Ask a question

I am using the Identity scaffolding to build a Blazor server-based website.

One of my customers is so bugged with the default "complex" password requirements, stating it makes the whole thing "unusable". Instead of lowering the password standard, I proposed a solution that use a password generator built-in on the registration page.

So I added a button to generate the password, but the button never ever worked. I set a breakpoint on the randomPassword() method but it was never hit.

This StackOverflow question pointed out that The newly introduced RenderMode settings is to blame, so I added @rendermode InteractiveServer on this page. Unfortunately, this didn't solve the problem, but also introduced a new one. I now have a NullReferenceException originating from \Components\Account\Shared\StatusMessage.razor. The HTTPContext is null for some reason.

image

>	EquipmentTrack.dll!EquipmentTrack.Components.Account.Shared.StatusMessage.OnInitialized() Line 22	C#
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(Microsoft.AspNetCore.Components.ParameterView directAndCascadingParameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(Microsoft.AspNetCore.Components.ParameterView parameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(ref Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.DiffContext diffContext, int frameIndex)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.DiffContext diffContext, int frameIndex)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.DiffContext diffContext, int newFrameIndex)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Microsoft.AspNetCore.Components.RenderTree.Renderer renderer, Microsoft.AspNetCore.Components.Rendering.RenderBatchBuilder batchBuilder, int componentId, Microsoft.AspNetCore.Components.RenderTree.ArrayRange<Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame> oldTree, Microsoft.AspNetCore.Components.RenderTree.ArrayRange<Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame> newTree)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(Microsoft.AspNetCore.Components.Rendering.RenderBatchBuilder batchBuilder, Microsoft.AspNetCore.Components.RenderFragment renderFragment, out System.Exception renderFragmentException)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(Microsoft.AspNetCore.Components.Rendering.RenderQueueEntry renderQueueEntry)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderHandle.Render(Microsoft.AspNetCore.Components.RenderFragment renderFragment)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(Microsoft.AspNetCore.Components.ParameterView directAndCascadingParameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(Microsoft.AspNetCore.Components.ParameterView parameters)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterView initialParameters)	Unknown
 	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.AddRootComponentAsync(int ssrComponentId, System.Type componentType, Microsoft.AspNetCore.Components.ComponentMarkerKey? key, Microsoft.AspNetCore.Components.WebRootComponentParameters parameters)	Unknown
 	[Resuming Async Method]	
 	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.<AddRootComponentAsync>d__3>(ref Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.<AddRootComponentAsync>d__3 stateMachine)	Unknown
 	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.<AddRootComponentAsync>d__3>(ref Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer.WebRootComponentManager.<AddRootComponentAsync>d__3 stateMachine)	Unknown
 	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.PerformRootComponentOperations.AnonymousMethod__0()	Unknown
 	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.PerformRootComponentOperations(Microsoft.AspNetCore.Components.RootComponentOperation[] operations, bool shouldWaitForQuiescence)	Unknown
 	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.UpdateRootComponents.AnonymousMethod__0()	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync.AnonymousMethod__10_0((System.Runtime.CompilerServices.AsyncTaskMethodBuilder completion, System.Func<System.Threading.Tasks.Task> asyncAction) state)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeWithThisAsCurrentSyncCtxThenSetResult<(System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>)>(System.Runtime.CompilerServices.AsyncTaskMethodBuilder completion, System.Action<(System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>)> callback, (System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>) state)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.SendIfQuiescedOrElsePost<(System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>)>(System.Action<(System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>)> callback, (System.Runtime.CompilerServices.AsyncTaskMethodBuilder, System.Func<System.Threading.Tasks.Task>) state)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync(System.Func<System.Threading.Tasks.Task> asyncAction)	Unknown
 	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContextDispatcher.InvokeAsync(System.Func<System.Threading.Tasks.Task> workItem)	Unknown
 	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.ComponentHub.UpdateRootComponents(string serializedComponentOperations, string applicationState)	Unknown
 	[Lightweight Function]	
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ExecuteMethod(Microsoft.Extensions.Internal.ObjectMethodExecutor methodExecutor, Microsoft.AspNetCore.SignalR.Hub hub, object[] arguments)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke.__ExecuteInvocation|18_0(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub> dispatcher, Microsoft.Extensions.Internal.ObjectMethodExecutor methodExecutor, Microsoft.AspNetCore.Components.Server.ComponentHub hub, object[] arguments, Microsoft.Extensions.DependencyInjection.AsyncServiceScope scope, Microsoft.AspNetCore.SignalR.IHubActivator<Microsoft.AspNetCore.Components.Server.ComponentHub> hubActivator, Microsoft.AspNetCore.SignalR.HubConnectionContext connection, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamCall)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke(Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor descriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext connection, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamResponse, bool isStreamCall)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<System.__Canon>.ProcessInvocation.AnonymousMethod__17_0((Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<System.__Canon>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor descriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext connection, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage hubMethodInvocationMessage) state)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.RunTask<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>(System.Func<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage), System.Threading.Tasks.Task<bool>> callback, (Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage) state)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.RunAsync<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>(System.Func<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage), System.Threading.Tasks.Task<bool>> callback, (Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage) state)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ProcessInvocation(Microsoft.AspNetCore.SignalR.HubConnectionContext connection, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage hubMethodInvocationMessage, bool isStreamResponse)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<System.__Canon>.DispatchMessageAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection, Microsoft.AspNetCore.SignalR.Protocol.HubMessage hubMessage)	Unknown
 	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.DispatchMessagesAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection)	Unknown
 	[Resuming Async Method]	
 	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.<DispatchMessagesAsync>d__21>.ExecutionContextCallback(object s)	Unknown
 	System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread threadPoolThread, System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
 	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.<DispatchMessagesAsync>d__21>.MoveNext(System.Threading.Thread threadPoolThread)	Unknown
 	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.AspNetCore.SignalR.HubConnectionHandler<System.__Canon>.<DispatchMessagesAsync>d__21>.ExecuteFromThreadPool(System.Threading.Thread threadPoolThread)	Unknown
 	System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()	Unknown
 	System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()	Unknown

This is the code in question:

@page "/Account/Register"

@using System.ComponentModel.DataAnnotations
@using System.Text
@using System.Text.Encodings.Web
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.WebUtilities
@using EquipmentTrack.Data

@inject UserManager<ApplicationUser> UserManager
@inject IUserStore<ApplicationUser> UserStore
@inject SignInManager<ApplicationUser> SignInManager
@inject IEmailSender<ApplicationUser> EmailSender
@inject ILogger<Register> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
@inject RoleManager<IdentityRole> RoleManager


@if (initialize)
{
    <PageTitle>初始化</PageTitle>
    <h1>初始化</h1>
    <button @onclick="@randomPassword">随机密码</button>
    <FluentGrid>
        <FluentGridItem xs="8" sm="4">
            <StatusMessage Message="@Message" />
            <EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser" FormName="register">
                <DataAnnotationsValidator />
                <hr />
                <FluentValidationSummary class="text-danger" role="alert" />
                <FluentStack Orientation="Orientation.Vertical">
                    <FluentTextField Name="Input.UserName" @bind-Value="Input.UserName" AutoComplete="username" Required="true" Placeholder="medical_equipment" Label="登录用户名" Style="width: 100%" />
                    <FluentValidationMessage For="() => Input.UserName" class="text-danger" />
                    <FluentTextField Name="Input.Department" @bind-Value="Input.Department" Required="true" Placeholder="医疗装备部" Label="科室" Style="width: 100%" />
                    <FluentValidationMessage For="() => Input.Department" class="text-danger" />
                    <FluentButton Appearance="Appearance.Neutral" @onclick="@randomPassword" Style="width: 100%">随机密码</FluentButton>  @* This doesn't work at all *@
                    <FluentTextField Name="Input.Password" @bind-Value="Input.Password" AutoComplete="current-password" Required="true" Placeholder="密码" Label="密码" Style="width: 100%" />
                    <FluentValidationMessage For="() => Input.Password" class="text-danger" />
                    <FluentTextField Name="Input.ConfirmPassword" @bind-Value="Input.ConfirmPassword" AutoComplete="new-password" Required="true" Placeholder="密码" Label="再输一遍密码" Style="width: 100%" />
                    <FluentValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
                    <FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent" Style="width: 100%">注册</FluentButton>
                </FluentStack>
            </EditForm>
        </FluentGridItem>
    </FluentGrid>
}
else
{
    <AuthorizeView Roles="@Constants.AdminRole">
        <Authorized Context="authContext">
            <PageTitle>新建用户</PageTitle>
            <h1>新建用户</h1>
            <FluentGrid>
                <FluentGridItem xs="8" sm="4">
                    <StatusMessage Message="@Message" />
                    <EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser" FormName="register">
                        <DataAnnotationsValidator />
                        <hr />
                        <FluentValidationSummary class="text-danger" role="alert" />
                        <FluentStack Orientation="Orientation.Vertical">
                            <FluentTextField Name="Input.UserName" @bind-Value="Input.UserName" AutoComplete="username" Required="true" Placeholder="general_surgery" Label="登录用户名" Style="width: 100%" />
                            <FluentValidationMessage For="() => Input.UserName" class="text-danger" />
                            <FluentTextField Name="Input.Department" @bind-Value="Input.Department" Required="true" Placeholder="普外科" Label="科室" Style="width: 100%" />
                            <FluentValidationMessage For="() => Input.Department" class="text-danger" />
                            <FluentTextField Name="Input.Password" @bind-Value="Input.Password" AutoComplete="current-password" Required="true" Placeholder="密码" Label="密码" Style="width: 100%" />
                            <FluentValidationMessage For="() => Input.Password" class="text-danger" />
                            <FluentTextField Name="Input.ConfirmPassword" @bind-Value="Input.ConfirmPassword" AutoComplete="new-password" Required="true" Placeholder="密码" Label="再输一遍密码" Style="width: 100%" />
                            <FluentValidationMessage For="() => Input.ConfirmPassword" class="text-danger" />
                            <FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent" Style="width: 100%">注册</FluentButton>
                        </FluentStack>
                    </EditForm>
                </FluentGridItem>
            </FluentGrid>
        </Authorized>
        <NotAuthorized>

        </NotAuthorized>
    </AuthorizeView>
}



@code {
    private IEnumerable<IdentityError>? identityErrors;

    [SupplyParameterFromForm]
    private InputModel Input { get; set; } = new();

    [SupplyParameterFromQuery]
    private string? ReturnUrl { get; set; }

    private string? Message => identityErrors is null ? null : $"Error: {string.Join(", ", identityErrors.Select(error => error.Description))}";

    private bool initialize => GetAdminCount().Result == 0;

    private async Task RegisterUser(EditContext editContext)
    {
        var user = CreateUser();

        await UserStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None);
        var emailStore = GetEmailStore();
        await emailStore.SetEmailAsync(user, Input.UserName, CancellationToken.None);

        user.DepartmentName = Input.Department;

        var result = await UserManager.CreateAsync(user, Input.Password);
        if (!result.Succeeded)
        {
            identityErrors = result.Errors;
            return;
        }

        if (initialize)
        {
            var addRoleResult = await RoleManager.CreateAsync(new IdentityRole(Constants.AdminRole));
            if (!addRoleResult.Succeeded)
            {
                identityErrors = addRoleResult.Errors;
                return;
            }
            addRoleResult = await UserManager.AddToRoleAsync(user, Constants.AdminRole);
            if (!addRoleResult.Succeeded)
            {
                identityErrors = addRoleResult.Errors;
                return;
            }
            await SignInManager.SignInAsync(user, isPersistent: true);
            RedirectManager.RedirectTo("/");
        }
        else
        {
            RedirectManager.RedirectTo("/UserManagement");
        }

        Logger.LogInformation("User created a new account with password.");

        // var userId = await UserManager.GetUserIdAsync(user);
        // var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
        // code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
        // var callbackUrl = NavigationManager.GetUriWithQueryParameters(
        //     NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
        //     new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl });

        // await EmailSender.SendConfirmationLinkAsync(user, Input.UserName, HtmlEncoder.Default.Encode(callbackUrl));

        // if (UserManager.Options.SignIn.RequireConfirmedAccount)
        // {
        //     RedirectManager.RedirectTo(
        //         "Account/RegisterConfirmation",
        //         new() { ["email"] = Input.UserName, ["returnUrl"] = ReturnUrl });
        // }
    }

    private ApplicationUser CreateUser()
    {
        try
        {
            return Activator.CreateInstance<ApplicationUser>();
        }
        catch
        {
            throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
                $"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor.");
        }
    }

    private IUserEmailStore<ApplicationUser> GetEmailStore()
    {
        if (!UserManager.SupportsUserEmail)
        {
            throw new NotSupportedException("The default UI requires a user store with email support.");
        }
        return (IUserEmailStore<ApplicationUser>)UserStore;
    }

    private sealed class InputModel
    {
        [Required]
        [Display(Name = "登录用户名")]
        public string UserName { get; set; } = "";

        [Required]
        [Display(Name = "科室")]
        public string Department { get; set; } = "";

        [Required]
        [StringLength(100, ErrorMessage = "{0}长度最少为{2}位,最大为{1}位。", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; } = "";

        [DataType(DataType.Password)]
        [Display(Name = "再输一遍密码")]
        [Compare("Password", ErrorMessage = "两个密码不一致。")]
        public string ConfirmPassword { get; set; } = "";
    }

    private async Task<int> GetAdminCount()
    {
        var usersInAdminRole = await UserManager.GetUsersInRoleAsync(Constants.AdminRole);
        return usersInAdminRole.Count;
    }

    private void randomPassword()
    {
        // This never get's executed
        var password = AuthUtils.GenerateRandomPassword();
        Input.Password = password;
        Input.ConfirmPassword = password;
        Logger.LogInformation("randompassword: "+ password);
    }
}

Then I tried to change the render mode in App.razor to InteractiveServer. Notice that the render mode was set to null when the route starts with /Account with the scaffolding. Unfortunately, things are even worse with the page being completely unusable, refershing itself once per second and with a memory leak about 1MB per second.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="EquipmentTrack.styles.css" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
    <link href="_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css" rel="stylesheet" />
    <script src="_content/Microsoft.FluentUI.AspNetCore.Components/js/loading-theme.js" type="text/javascript"></script>
    <loading-theme storage-name="theme"></loading-theme>
    <HeadOutlet @rendermode="RenderModeForPage" />
</head>

<body>
    <Routes @rendermode="RenderModeForPage" />
    <script src="_framework/blazor.web.js"></script>
</body>

<FluentDesignTheme Mode="DesignThemeModes.System" StorageName="theme" />


</html>

<script>
    window.playSound = function () {
        var audio = new Audio('notify.mp3'); // replace 'sound-file.mp3' with the path to your sound file
        audio.play();
    }
</script>

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
        ? null
        : InteractiveServer;
}

For your reference, this should be the template:
https://github.com/dotnet/Scaffolding/blob/main/src/Scaffolding/VS.Web.CG.Mvc/Templates/BlazorIdentity/Pages/Register.tt

To solve this problem, I could:

  1. Tell my customer to deal with it
  2. Use JavaScript to generate the password

But the ultimate question is, why Identity doesn't with InteractiveServer render mode?

Include provider and version information

Microsoft.VisualStudio.Web.CodeGeneration.Design version: 8.0.2
Target framework: .NET 8
Operating system: Windows 11 Pro
IDE: (e.g. Visual Studio 2022 17.10.0 Preview 7.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant