aspnetcore blazor navigation from razor component to razor page
Asked Answered
C

3

4

I am attempting to redirect from a razor component to a razor page. If user is not authorized I want to redirect from current razor component to Login Razor Page.

I have redirect to login component

public class RedirectToLogin : ComponentBase
    {
        [Inject]
        protected NavigationManager NavigationManager { get; set; }

        protected override void OnInitialized()
        {
            NavigationManager.NavigateTo("./Identity/Account/Login",true);
        }
    }

this line throws an error NavigationManager.NavigateTo("./Identity/Account/Login");

Microsoft.AspNetCore.Components.NavigationException: 'Exception of type 'Microsoft.AspNetCore.Components.NavigationException' was thrown.'

The assumption i have come to is that the problem is routing from a razor component to a razor page.

Calfskin answered 6/2, 2020 at 21:19 Comment(2)
i have same Exception. How you resolve this error?Phonologist
@Phonologist posted answer to what the solution was that we accepted.Calfskin
C
1

I got a redirect to a not authorized page, using the Router below.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView  RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
            <NotAuthorized>
                <div class="container">
            <h1>Sorry</h1>
            <p>You're not authorized to reach this page.</p>
            <p>You may need to log in as a different user.</p>
            <a href="Identity/Account/Login">Log in</a>
        </div>
                @*<RedirectToLogin />*@
            </NotAuthorized>
            <Authorizing>
                <div class="container">
                    <h1>Authentication in progress</h1>
                    <p>Leave your hands on the keyboard,  scanning your fingerprints.  Ain't technology grand.</p>
                </div>
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

This sufficed for the app for now.

Calfskin answered 8/7, 2020 at 12:58 Comment(1)
Sorry for necro comment, but <Authorizing> directions were funny. :)Salesgirl
G
1

If someone is looking for a complete solution, this is how I did it.

Solution

Step 1: Create a razor component named RedirectToLogin.razor wherever you want.

For eg: I'm creating it inside Areas/Identity/Components

And add the following code to this file:

@inject NavigationManager Navigation
@code {
    [Parameter]
    public string ReturnUrl { get; set; }

    protected override async Task OnInitializedAsync()
    {
            ReturnUrl = "~/" + ReturnUrl;
            Navigation.NavigateTo("Identity/Account/Login?returnUrl=" + ReturnUrl, true);
            await base.OnInitializedAsync();
    }
}

Step 2: Use this component from App.razor inside <NotAuthorized></NotAuthorized>:

@inject NavigationManager Navigation
@using HMT.Web.Server.Areas.Identity.Components

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @if (!context.User.Identity.IsAuthenticated)
                    {
                        <RedirectToLogin ReturnUrl="@Navigation.ToBaseRelativePath(Navigation.Uri)" />
                    }
                    else
                    {
                        <p role="alert">Sorry, you're not authorized to view this page.</p>
                    }
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Complete source code

https://github.com/akhanalcs/blazor-server-auth/tree/feature/LayoutWithIdentityPages

Demo

Start the app and try to get to an authorized view from the browser (Counter page here as an example):

You'll be redirected to Login page:

You'll log in successfully and get to the Counter page:

Granite answered 7/12, 2022 at 18:56 Comment(1)
When my redirect comes back my URL is: https://localhost:5001/~/workflows it includes the ~/ is there a reason for that?Unparliamentary
G
0

This is an easy fix, it actually has nothing to do with authorization or so. You're doing the navigation part right. The problem here is that for some reason you can't use NavigationManager.NavigateTo() in OnInitialized(). It always throws this exception as you might have figured out already.

But the good thing is: The workaround is simple, yet not amazing: You just move NavigationManager.NavigateTo() into OnAfterRender(). That method gets called after the component has been rendered, so its close enough. However your page gets rendered, meaning you would need to handle that.

The answers to this question also answer yours.

Gasholder answered 5/8, 2023 at 18:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.