0
votes

I need to navigate from a razor page to a blazor page, so I tried to do:

public class LoginCallbackModel : PageModel
{
    private readonly NavigationManager navigationManager;

    public LoginCallbackModel(
        NavigationManager navigationManager)
    {
        this.navigationManager = navigationManager;
    }

    public async void OnGet()
    {
        if (User.Identity.IsAuthenticated)
        {
            var accessToken = await HttpContext.GetTokenAsync("access_token");
            var idToken = await HttpContext.GetTokenAsync("id_token");
        }

        navigationManager.NavigateTo("Dashboard");
    }
}

But I get this exception:

RemoteNavigationManager' has not been initialized

I also tried:

RedirectToPage("Dashboard");

But this doesn't work either.

I need to use a razor page because I have access to the HttpContext. So how can I navigate to a component from the page?

1
As a first try, I would redirect to the page and method where the view holds the corresponding <component type="typeof(YourRootComponentType)" />. If you need to pass some arguments to your component, you can use the NavigationManager to read parts from the URL after the component has been initialized.Just the benno
More information please. Is the (Non Blazor) page on the same site (Web Application) as the Blazor application? If so then how is your startup.cs configured. What URL are you using for the Blazor SPA.MrC aka Shaun Curtis

1 Answers

0
votes

However there's a step that I might be missing and I will create a separate question. The problem here is how to redirect from a razor page to a blazor page. I've tried different flavors of Redirect but none are working.

Yes, create a separate question. In the meanwhile, here's the answer:

Create a file named Login.cshtml.cs. This file should be called from Blazor (RedirectToLogin.razor).

This is the code of RedirectToLogin.razor

@inject NavigationManager NavigationManager

    @code{
    
        [Parameter]
        public string ReturnUrl { get; set; }
    
        protected override void OnInitialized()
        {
    
            NavigationManager.NavigateTo($"login?redirectUri={ReturnUrl}", forceLoad: true);
    
        }
    
    }

And this is the code of Login.cshtml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.IdentityModel.Tokens;


namespace <namespace of your app>.Pages
{
    public class LoginModel : PageModel
    {
       
        public async Task OnGet(string redirectUri)
        {
            await HttpContext.ChallengeAsync("oidc",
                   new AuthenticationProperties
                      {
                         RedirectUri = redirectUri,
                         IsPersistent = true,
                          ExpiresUtc = DateTimeOffset.UtcNow.AddHours(15)  
                                              // login expiration
                      });

        }
     
    }
}

The code above performs Authorization request to Auth server which return Authorization Code. RedirectUri will contain the url to redirect to when the Authorization request returns. You may set it to "Dashboard", not from ChallengeAsync but from your RedirectToLogin component (RedirectToLogin.razor). That is all...

Once again, the flow is RedirectToLogin (Blazor) => Login.cshtml.cs (cuurent code) => Auth server => Blazor( perhaps, "Dashboard")

By the time you arrive at the "Dashboard", the access token should be stored in your local storage if you've used the code I provided in the first answer. If you ask how then the answer is: this code do the magic:

var token = await HttpContext.GetTokenAsync("access_token");

This code instruct the http context to get the access token in exchange for the Authorization Code. When does it happen ? When your Blazor is accessed 'for the first time'; that is to say, before it is created at all - this is the time when _Host.cshtml is fulfilling its role, which includes a Get operation (mind you it's http request that is handled by a Get method:

public async Task OnGetAsync()
        {
            var token = await HttpContext.GetTokenAsync("access_token");
            var idToken = await HttpContext.GetTokenAsync("id_token");
            AccessToken = token;
            IDToken  = idToken;
        }

It's all in my first answer.