NavigationError on NavigateTo - asp.net-core

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.

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.

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>

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>

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...

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.

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

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

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.

Related

Blazor Server - Redirect to Login in Anonymous component - Sorry, there's nothing at this address

This is weird, I have a pge for user onboarding after he is invited to the app.
At the end of the onboarding process I wanted to sign in him programatically, but because its Blazor server component, it says that I cant change the header bla bla.. so I tried to redirect him to Login instead like this:
private void OnReadyClick()
{
NavigationManager.NavigateTo("/Identity/Account/Login");
}
Also tried like this:
private void OnReadyClick()
{
NavigationManager.NavigateTo("/Account/Login");
}
And just sending him to index and let the app redirect him when sees he is not authenticated:
private void OnReadyClick()
{
NavigationManager.NavigateTo("/");
}
Also tried in the component to add this:
if(redirect)
{
<RedirectToLogin/>
}
All the options above make the browser return:
Sorry, there's nothing at this address
But if I refresh the page it goes to sign in page...
Why is it returning upon redirect "Sorry, there's nothing at this address" and upon refresh works?
Regards
Try adding the force load parameter to your redirect:
NavigationManager.NavigateTo("/Identity/Account/Login",true);
But also, I've had this issue occur if you have render-mode="Server" for your app inside your _Host.cshtml file, instead of render-mode="ServerPrerendered".
Try changing:
<component type="typeof(App)" render-mode="Server"/>
to
<component type="typeof(App)" render-mode="ServerPrerendered" />
Well after a while I still not understand why the browser gave me that response, but I solved the problem by using an anchor href like bellow:
<a class="custom-btn rounded-btn main-btn" href="Identity/Account/Login">
#GenericConst.Ready
<img src="assets/icons/arrow-right-ic.svg" />
</a>
Still would like to know the reason for the "Sorry, there's nothing at this address" msg, but if anyone ends up in the same situation just follow this solution.

Blazor WASM stuck on "Authorizing..." and "Completing login..."

After upgrading to .Net 5.0 my blazor WASM app started getting stuck on "Authorizing..." (it gets stuck when the user was already logged in, first load with redirect to login screen works fine, so I have to clear the cache if I want it to work) and "Completing login..." (with a URL like https://localhost:5001/authentication/login-callback?code=51FEF78805049242F1092A249B1746393790AE956B1FC2136092AE0924B3FB42&scope=openid%20profile%20email%20MyApp.WebAPI&state=e8bffbd2b93f44dc8a261cf6d65c6165&session_state=eE0yRtJI0fkjptvZSIfiUsvuHAQoyNStmS_kv--Wcv0.DCACB551F4CC63841C2615456DD4B9BF) - if I go to localhost:5001 after it got stuck on "Completing login..." I am finally logged in.
Initially it was working fine on most modern computers and the issue was only visible on slow computers (~8 year old laptop for instance). However, while I tried to understand the issue and fix it, I managed to brake it completely on my developer laptop as well, where the main branch still works mostly fine.
Creating a new ASP.Net Core app with authentication with IdentityServer4 works just fine, no issues there.
My issue looks similar to https://github.com/dotnet/aspnetcore/issues/26195 - however, I'm using only IdentityServer4 and I don't see any exceptions in the developer console.
I tried to reduce the code to a bare minimum, so here is the Program.cs:
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddApiAuthorization();
builder.Services.AddSingleton<IStringLocalizer>(serviceProvider =>
{
var factory = serviceProvider.GetRequiredService<IStringLocalizerFactory>();
return factory.Create(typeof(SharedResource));
});
builder.Services.AddLocalization();
builder.Services
.AddBlazorise()
.AddBootstrapProviders();
builder.Logging.SetMinimumLevel(LogLevel.Trace);
var host = builder.Build();
host.Services.UseBootstrapProviders();
await host.RunAsync();
}
the App.razor:
#inject IStringLocalizer S
<ThemeManager>
<CascadingAuthenticationState>
<Router AppAssembly="#typeof(App).Assembly" PreferExactMatches="#true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)">
<NotAuthorized>
#if (context.User.Identity?.IsAuthenticated ?? false)
{
<p>#S["You don't have enough permissions to access this page."]</p>
}
else
{
<RedirectToLogin />
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="#typeof(MainLayout)">
<NotFoundError>
</NotFoundError>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</ThemeManager>
The MainLayout.razor:
#inherits Microsoft.AspNetCore.Components.LayoutComponentBase
<header>
</header>
<main>
#Body
</main>
The Authentication.razor:
#page "/authentication/{action}"
#using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="#Action" />
#if (Action == "logged-out")
{
<RedirectToLogin RedirectBackToRoot="true"></RedirectToLogin>
}
#code{
[Parameter]
public string? Action { get; set; }
}
The problem is, that it just gets stuck and I don't even see what could be wrong. The one dependency I have here is on https://github.com/stsrki/Blazorise - however, I added the same dependency also to the new application, and that one still works.
Any idea how I could identify the issue?
The answer was, that the reference of the JS library pace.js broke the authentication. A new version of the library was released (and automatically updated) around the same time, we upgraded to .Net 5.0 so not sure if it was a .Net 5 issue or the library issue.
I also experienced hanging during login but years after this post. Mine happened with .NET 6. I noticed Microsoft.AspNetCore.Authentication.JwtBearer was version 6.0.8 and that version had just been released last week. I downgraded to 6.0.7 and the hanging went away.

Blazor Server Side, call JavaScript function that resides in a CDN from a .razor page when it renders

I'm trying to include Bootstrap for Material Design into my Blazor Server Side project. I have it working perfectly in a plain HTML file, but the issue with Blazor comes with a script. which I assume needs to run after a page was rendered. The script calls a function from a CDN.
<script src="https://unpkg.com/bootstrap-material-design#4.1.1/dist/js/bootstrap-material-design.js" integrity="sha384-CauSuKpEqAFajSpkdjv3z9t8E7RlpJ1UP0lKM/+NdtSarroVKu069AlsRPKkFBz9" crossorigin="anonymous"></script>
I have added the CDN in my tag on _Hostcshtml and have verified that it is correctly called when system is compiled.
The function in question (which does validation on form input fields) is
<script>$(document).ready(function() { $('body').bootstrapMaterialDesign(); });</script>
On the plain HTML file this call is just in the tag after the CDN call.
My problem is to correctly call the .bootstrapMaterialDesign in my OnAfterRenderAsync in Bootstrap.
Current code, which is obviously incorrect is:
#page "/signUpContak"
#layout SignUpLayout #inject IJSRuntime JSRuntime;
....
#code { protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) await JSRuntime.InvokeAsync<>("bootstrapMaterialDesign"); } }
I hope this makes sense. The implementation documentation for Bootstrap Material Design is at https://fezvrasta.github.io/bootstrap-material-design/docs/4.0/getting-started/introduction/
I managed to fix the issue by doing the below.
In my _host.cshtml I added:
function InitializeBootstrapMaterialDesign() {
$(document).ready(function ()
{$('body').bootstrapMaterialDesign(); });
}
And on SignUpContak.razor I added:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("InitializeBootstrapMaterialDesign");
}

How to sign out over HttpContext in server-side Blazor

I access the HttpContext in a Blazor server-side view to manually log out. I added this line to Startup.cs: services.AddHttpContextAccessor(); and inject it in the view with #inject IHttpContextAccessor HttpContextAccessor.
I've got a log out button which tries to execute this code:
await HttpContextAccessor.HttpContext.SignOutAsync("Cookies");
but I get the following error message:
System.InvalidOperationException: 'Headers are read-only, response has already started.'
How can I prevent this error?
If you scaffolded Identity and overridden the old "LogOut.cshtml" from when you created the project via template, the Logout button won't logout. Assume you've used the default IdentityUser model. I ran into this issue and just wanted to add this if anyone else had this problem as well. I'm using Blazor Server with .Net 5.0.3's template. You can remove the Logout.cshtml.cs after as well.
Replace this \Areas\Identity\Pages\Account\LogOut.cshtml
#page
#model LogoutModel
#{
ViewData["Title"] = "Log out";
}
<header>
<h1>#ViewData["Title"]</h1>
#{
if (User.Identity.IsAuthenticated)
{
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="#Url.Page("/", new { area = "" })" method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Click here to Logout</button>
</form>
}
else
{
<p>You have successfully logged out of the application.</p>
}
}
</header>
Replace with
#page
#using Microsoft.AspNetCore.Identity
#attribute [IgnoreAntiforgeryToken]
#inject SignInManager<IdentityUser> SignInManager
#functions {
public async Task<IActionResult> OnPost()
{
if (SignInManager.IsSignedIn(User))
{
await SignInManager.SignOutAsync();
}
return Redirect("~/");
}
}
This tripped me up too, but you need the logout functionality to be on a Razor Page (not a Blazor component). Create a Logout page and put your logout code in the OnGetAsync() method.
Your logout button can then link to the logout page.
http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/4316/A-Demonstration-of-Simple-Server-side-Blazor-Cookie-Authentication.aspx - this is a helpful example
Don't use IHttpContextAccessor.
I guess that you're using ASP.NET Core Blazor authentication and authorization new system. If not, then start with it right now. Live is too short to be wasted over other things. This is the best product created so far for Blazor's authentication and authorization, and it is based on the Identity UI (This is not Blazor, of course). Additionally, there are a couple of Components which enable controlling the flow of authentication and authorization in your application, such as displaying a "Log in" button and a "Log out" button in your layout, interchangeably altering depending on your authentication state, etc.
Please, go to this page and start learning this excellent system, and then come here for specific issues you face:
https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.0&tabs=visual-studio
Hope this helps...

Kendo UI Upload Async Error

I downloaded a trial version of Kendo.UI, so logging onto the forums, at this stage is not possible, hoping someone on here can help me solve this problem.
I'm trying to implement the async upload onto a basic MVC 4 application. I've added a reference to the Kendo.UI.MVC wrappers, and added the necessary namespace Kendo.UI.MVC to both web.config files (root and under Views).
If I implement a basic uploader on my landing view (index.cshtml) it works fine:
<form action="/Home/Save" method="post">
#(Html.Kendo().Upload().Name("files"))
<input type="submit" value="Submit" />
</form>
However, as soon as I add the Save() method to Async, I get an "index was out of range" exception. I know it's the save method, because if I just add "AutoUpload(true)" without an action reference, it does not throw an exception. If I just add "Remove("Remove", "Home")" it still shows the Select button, without an error, but the "Save("Save", "Home")" method keeps throwing the mentioned exception.
I followed the examples that ship with the trial to the letter and it should web working, yet it does not.
View (index.cshtml):
#(Html.Kendo()
.Upload()
.Name("files")
.Async(async => async
.Save("Save", "Home")))
-- Error is being thrown on the above statement
#(Html.Kendo()
.Upload()
.Name("files")
.Async(async => async
.AutoUpload(true)))
-- this line works
Controller (HomeController):
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Save(IEnumerable<HttpPostedFile> files)
{
// I just want the break-point to be hit
// does not due to IndexOutOfRange exception being thrown
return Content("");
}
}
The only thing that seems wrong is the Razor syntax:
(#Html.Kendo()
should be
#(Html.Kendo()
I was able to run your code with this small change.
Updated the MVC templates for Visual Studio and it works. Thanks.