Search code examples
c#asp.net-coreblazor-server-sideblazor-webassemblyasp.net-core-7.0

error when pass user name from login page to another page Dashboard?


I work on blazor web app with .net core 7 . I get error when try to pass user name from login page to another page dashboard after use login success.

I pass data using session storage from login page to dashboard page .

I work on Blazor Server Side.

error happen on dashoard.razor After get User Name from sessions storage .

I get error

InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
Microsoft.AspNetCore.Components.Server.Circuits.RemoteJSRuntime.BeginInvokeJS(long asyncHandle, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(long targetInstanceId, string identifier, CancellationToken cancellationToken, object[] args)
Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(long targetInstanceId, string identifier, object[] args)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage.GetAsync<TValue>(string purpose, string key)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
UC.AppRepository.UI.Pages.Dashboard.GetUserName() in Dashboard.razor
+
        ProtectedBrowserStorageResult<string> result = await sessionStorage.GetAsync<string>("NewUserName");
UC.AppRepository.UI.Pages.Dashboard.OnInitializedAsync() in Dashboard.razor
+
       await GetUserName();

code details

loginBase.cs (First page that I want to start from it)

public async Task Login()
{
string UserName = userDto.UserName;
SetUserName(UserName);

}
private async Task SetUserName(string UserName)
{
          
await sessionStorage.SetAsync("NewUserName", UserName);
NavigationManager.NavigateTo("/Dashboard", true);
}

DashBoard.razor(second page I need to reach to it)

@inject ProtectedSessionStorage sessionStorage
@code{
public string? UserName { get; set; }
protected override async Task OnInitializedAsync()
    {
        
       await GetUserName();
    }
}



private async Task GetUserName()
    {
        ProtectedBrowserStorageResult<string> result = await sessionStorage.GetAsync<string>("NewUserName");

        if (result.Success)
        {
            UserFullName = result.Value;
        }
       
    }
<div>Welcome  @UserFullName</div>

updated answer

Do you mean pass value to Razor Page from Blazor Component?

yes exactly


Solution

  • According to this official document, you can only safely run interop code in the OnAfterRenderAsync lifecycle method.

    Since this runs after the render cycle, you will need to notify your component to re-render using StateHasChanged() once your asynchronous process completes.

    Try this way:

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await GetUserName();
            StateHasChanged();
        }
    }
    

    Update:

    If the value you pass is more complicated, you can choose the way you are using now, store the value in the Session, and then read it in the Razor Page.

    If the value you pass is relatively simple, you can pass it through the route. For example, passing a string Name:

    Razor Component:

    <button class="btn btn-primary" @onclick="Click">Click me</button>
    @code {
        public string Name = "Name";
        private void Click()
        {
            NavigationManager.NavigateTo("/Test?Name=" + Name,true);
        }
    }
    

    Test.cshtml.cs:

    public class TestModel : PageModel
    {
        public string Name { get; set; }
        public void OnGet(string name)
        {
            Name = name;
        }
    }
    

    Test.cshtml:

    @page "/Test"
    @model BlazorApp.Pages.TestModel
    
    <div>@Model.Name</div>
    

    Test Result:

    enter image description here

    enter image description here