50

I'm trying out Blazor ServerSide and created a Component to Redirect To the Login Page when a user is not logged in.

@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager;

@code {
/// <inheritdoc />
protected override Task OnInitializedAsync()
{
    NavigationManager.NavigateTo("Login");
    return Task.CompletedTask;
}

}

But always when "NavigateTo" is called the following exception is thrown:

"Microsoft.AspNetCore.Components.NavigationException: Exception of type 'Microsoft.AspNetCore.Components.NavigationException' was thrown.
   at Microsoft.AspNetCore.Components.Server.Circuits.RemoteNavigationManager.NavigateToCore(String uri, Boolean forceLoad)
   at Microsoft.AspNetCore.Components.NavigationManager.NavigateTo(String uri, Boolean forceLoad)
   at ApplySupportTool.Blazor.Pages.RedirectToLogin.OnInitializedAsync() in C:\\Users\\padruttn\\Documents\\git\\ApplySupportTool\\src\\ApplySupportTool.Blazor\\Pages\\RedirectToLogin.razor:line 8"

Interesstingly the navigation is made despite the exception. I also tried to call it with the path "/login" but the same behaviour here.

3
  • 24
    That's got to be one of the worst (least descriptive) exceptions I've ever seen. GG Microsoft. Commented Aug 14, 2020 at 1:16
  • github.com/dotnet/aspnetcore/issues/… Commented May 25, 2022 at 21:09
  • If someone is looking for a complete answer, take a look at this: stackoverflow.com/a/74721678/8644294 Commented Dec 7, 2022 at 19:01

14 Answers 14

61

There is an open issue on github for this problem. See also the preceeding issue where a possible workaround is mentioned: putting the NavigateTo method into OnAfterRender instead of OnInitialized.

Sign up to request clarification or add additional context in comments.

1 Comment

The issue is no longer open and still remains unfixed, but moving the call to OnAfterRender works a charm!
18

use OnInitializedAsync replace OnInitialized

protected override async Task OnInitializedAsync()
{
    nav.NavigateTo("/login", true);
    await base.OnInitializedAsync();
}

2 Comments

This is the correct solution
This doesn't solve the issue for me. The exception is triggered, but the NavigateTo works for the user.
17

I needed to put this into OnInitialized rather than OnAfterRender, so had to go with the render-mode="Server" method, though apparently this isn't recommended.

It also states in the GitHub issue that this only happens in debug, not release, so a middle ground option is to change _Host.cshtml to contain:

<environment include="Staging,Production">
    <component render-mode="ServerPrerendered" type="typeof(App)" />
</environment>
<environment include="Development">
    <component render-mode="Server" type="typeof(App)" />
</environment>

2 Comments

I think this is the preferred solution until it is fixed!
I think that a better solution to this is to set a flag in your code behind, and then perform the navigation where you are expected to, after the rendering is complete. You can use that same flag to optimize the rendering in the scenario.
16

Note that the following may be considered a workaround:

You may also change your method to the following including the "async" keyword to its signature, there is going to be a complaint about not using await, but in exchange you are not going to need a return value. Since it doesn't have an 'await' the effect is kinda the same as the synchronous version, but without the exception being thrown.

protected override async Task OnInitializedAsync()
{
    NavigationManager.NavigateTo("Login");
}

Here is an example where i am using a RedirectToLogin.razor component in my routing

@inject NavigationManager NavigationManager

@code{

    protected override async Task OnInitializedAsync()
    {
        var returnUrl = "~/" + NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
        NavigationManager.NavigateTo($"Identity/Account/Login?returnUrl={returnUrl}", forceLoad:false);
    }

}

And in my App.razor

 <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <RedirectToLogin />
                </NotAuthorized>
            </AuthorizeRouteView>
 </Found>

1 Comment

Can you explain "~/"? This does not work for me locally and I end up with localhost:1234/~ which is not found.
10

Old post, but - if you are running a Blazor Server app, this behavior only happens if render-mode is "ServerPrerendered". Disabling Pre-rendering by changing the mode to "Server" makes the exception not be thrown in the first place:

<app>
    <component type="typeof(App)" render-mode="Server" />
</app>

I've searched current Blazor Documentation and change notes, and haven't found any mention of this, so just in case it helps somebody else...

1 Comment

It works, but its a "sledge-hammer for a nail" fix :-s
10

I ran into the same problem and filed issue #28355. The official answer is, that it is save to ignore the exception when NaviagteTo is placed in OnInitialized. Here is the answer from javiercn:

Yes, it is completely safe to ignore it. The debugger stops because it is configured to do so, but in this case the exception is always handled. You can turn-off breaking on this exception if it's caught on the debugger settings.

Issue #13582 deals with how to prevent the debugger from stopping at this exception.

Comments

10

This issue persists on .Net 9,

In my case, I only encounter it whenever my debugger is on. The current solution is to put your NavigationManager code in try-catch or simply ignore it.

.Net team planned to fix it in .Net 10. You can track the issue on Github.

1 Comment

Yes it happens only in 'Debug' mode not in 'Release' mode. Also, in my case only first time in my Login, if logout and login again then login redirection not creating problem for me.
3

I had this when I tried to call the navigateto from another thread. render-mode = "Server" - solved the problem

Comments

1

For me, it was called on the wrong thread. This will help:

            await InvokeAsync(() => NavigationManager.NavigateTo("/chat"));

Comments

0

In a Blazor 8 web app the OnInitialized/Async doesn't work when you need to redirect before the layout rendering.

The routing code (Routes.razor) is something like:

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)">
                <NotAuthorized>
                    <RedirectToLogin />
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="routeData" Selector="#page-container" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(Layout.MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

In this case the redirect is triggered immediately and the OnInitializedAsync triggers the same error. The only solution is to use an OnAfterRender method, the following is my RedirectToLogin.razor:

@inject NavigationManager NavigationManager

@code {
    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true);
        return base.OnAfterRenderAsync(firstRender);
    }
    
    // https://github.com/dotnet/aspnetcore/issues/53996
    // We need to use the OnInitializedAsync method instead of the OnInitialized method
    // {
    //     NavigationManager.NavigateTo($"Account/Login?returnUrl={Uri.EscapeDataString(NavigationManager.Uri)}", forceLoad: true);
    // }
}

Comments

0

I moved the redirect to OnParameterSet from OnInitialized. It helped me.

    protected override void OnParametersSet()
    {
        Navigation.NavigateTo("/", forceLoad: true);
    }

Comments

0

In .NET 10 add this line:

<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>

in ... .csproj file like:

<PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    ...

    <BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
  </PropertyGroup>

Comments

-1

In .NET 5.0, in the _host.cshtml file. Past the following @(await Html.RenderComponentAsync(RenderMode.Server)) in the line after the "blazor_error_ui" section.

1 Comment

On Net5.0 I get an error: "Error CS0411 The type arguments for method 'HtmlHelperComponentExtensions.RenderComponentAsync<TComponent>(IHtmlHelper, RenderMode)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
-1

A simple workaround that i used is to encapsulate the navigation code in a try catch block

                @try
                {
                    if (context != null)
                    {
                        if (!context.User.Identity.IsAuthenticated)
                        {
                            var returnUrl = _navigation.ToBaseRelativePath(_navigation.Uri);
                            returnUrl = "~/" + returnUrl;
                            _navigation.NavigateTo($"Identity/Account/Login?returnUrl={returnUrl}", forceLoad: true);
                        }
                    }
                }
                catch
                {
                }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.