Blazor Route Not Found - How do I go to the site base? - blazor-server-side

I don't want a custom page. I just want to redirect to the index page.
<Router AppAssembly="#typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)" />
</Found>
<NotFound>
#* go to site base *#
</NotFound>
</Router>

I finally found an answer here (under the Found and NotFound Templates section):
https://chrissainty.com/introduction-to-routing-in-blazor/

Related

Blazor Authentication - Http calls does work for anonymous

I have been playing with blazor with .net 5.0. I am stuck with a simple but annoying issue: I am trying to load data from API but every call to the Server blazor expects the user to be signed in.
I understood if we took out [Authorize] tag from the API controller and don't have #attribute [Authorize] in the razor page, and that would be it. But I am struggling to understand why my API call still expects AccessToken in protected override async Task OnInitializedAsync() the error messages don't say much around why.
Microsoft.AspNetCore.Components.WebAssembly.Authentication.AccessTokenNotAvailableException: ''
at Microsoft.AspNetCore.Components.WebAssembly.Authentication.AuthorizationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
I haven't touched the App. cs file of the web assembly..
Can anyone help please.
<CascadingAuthenticationState>
<Router AppAssembly="#typeof(Program).Assembly" PreferExactMatches="#true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)">
<NotAuthorized>
#if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
<Authorizing>
<h4>Authentication in progress...</h4>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="#typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
I figured the solution ... should have looked at it first.
it was actually the App.CS fill in the Client Project. Http endpoint is initiated there, and by default the code-gen adds BaseAddressAuthorizationMessageHandler to the httpclient.
builder.Services.AddHttpClient("private", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
how I solved it was using named clients one for Private and one for Public like so
builder.Services.AddHttpClient("private", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddHttpClient("public", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));
and in pages inject IHttpClientFactory
#inject IHttpClientFactory ClientFactory
and create a named client from the factory.
var client = ClientFactory.CreateClient("public");
This worked.
I think it's because you have CascadingAuthenticationState encapsulating both Foundcontext and NotFound since what it does is to pass authorization information down to other components. So, wrapping it around all your components prevents access to unauthorized users. Try this instead
<Router AppAssembly="#typeof(Program).Assembly" PreferExactMatches="#true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)">
<NotAuthorized>
#if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
<Authorizing>
<h4>Authentication in progress...</h4>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="#typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
<CascadingAuthenticationState>
</NotFound>
</Router>

Re render Header in ReactJs

I have index.js as below code:
<relevant imports>
function Header(){
return(<HeaderComponent/>);
}
ReactDOM.render(
<div>
<Router>
<div>
<Switch>
<Route path="/page1" component={page1} />
<Route path="/page2" component={page2} />
<Route path="/page3" component={page3} />
<Route path="/home" component={PortfolioPageComponent} />
<Route path="/" component={WelcomePage} />
</Switch>
</div>
</Router>
</div>,
document.getElementById('root')
);
ReactDOM.render(<Header />, document.getElementById('page-header'));
now when I am opening my app it goes to WelcomePage .In this component I have authorization logic. once Authetication is done, Page is redirecting to PortfolioPageComponent but header component is NOT getting reloaded.
How can I re-render Header component also on each redirection?
Putting the header component OUTSIDE the switch component allows it to render with each route. This way, no matter which route you navigate to, the components outside of the switch will always be rendered. This could be including a header before the switch component and a footer afterwards.

CascadingAuthenticationState and NotFoundContent tags not working in Blazor

So I've been following this tutorial for implementing authorization/authentication on my blazor client app (asp.net core hosted). Everything worked ok until I started working on client side ("Configuring client-side Blazor" subtitle in the tutorial). I've successfully installed Blazored.LocalStorage nuget package. But I'm failing at adding "CascadingAuthenticationState" and "NotFoundContent" components to my App.razor file. The compiler can't see these componnents and asks to add using directives.
Here's the _Imports.razor:
#using Microsoft.AspNetCore.Components.Forms
#using Microsoft.AspNetCore.Components.Routing
#using Microsoft.AspNetCore.Components.Web
#using Microsoft.JSInterop
#using Musical_WebStore_BlazorApp.Client
#using Musical_WebStore_BlazorApp.Client.Shared
#using Microsoft.AspNetCore.Authorization
#using Blazored.LocalStorage
Here's the App.razor that's not working (and I'm asking to help me to get it working):
<CascadingAuthenticationState>
<Router AppAssembly="typeof(Program).Assembly">
<NotFoundContent>
<p>Sorry, there's nothing at this address.</p>
</NotFoundContent>
</Router>
</CascadingAuthenticationState>
Here's the App.razor that was working (I had it by default):
<Router AppAssembly="#typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="#routeData" DefaultLayout="#typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="#typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Here are the versions of the projects:
Blazor.Client (Microsoft.AspNetCore.Blazor nuget package): 3.0.0-preview9.19465.2
ASP.NET Core (Microsoft.AspNetCore.Blazor.Server nuget package): 3.0.0-preview9.19465.2
Shared: .NET Standard 2.0 library
How do I solve this problem? It looks like these components should be available by default. And even if not, I couldnt find the namespace for these components on the internets.
You need to install the Microsoft.AspNetCore.Components.Authorization package from NuGet. This package didn't exist at the time I wrote that article. Once you've installed it and added a using to the _Imports.razor you should be good to go.

React-Router nested routes names

I would like to implement that kind of routes in react-router v4.
/auth => auth home page
/auth/login => login page
/auth/register => register page
/auth/forgot => lost password page
/auth/reset => change password page
It doesn't work with <Switch> because it first match /auth and render the associated component. So as I click on the link to go to the login page for instance it renders the Auth Component and not the Login Component.
How can I implement that behavior with react-router ?
I tried nested routing but if I take the same example as before, It would renders the Auth Component + Login Component.
Thanks.
You can add the exact prop to your /auth route:
<Switch>
<Route exact path='/auth' component={Auth} />
<Route path='/auth/login' component={Login} />
<Route path='/auth/register' component={Register} />
<Route path='/auth/forgot' component={ForgotPassword} />
<Route path='/auth/reset' component={ChangePassword} />
</Switch>
Alternatively, you could move your /auth route to the end of the list so other routes match first:
<Switch>
<Route path='/auth/login' component={Login} />
<Route path='/auth/register' component={Register} />
<Route path='/auth/forgot' component={ForgotPassword} />
<Route path='/auth/reset' component={ChangePassword} />
<Route path='/auth' component={Auth} />
</Switch>
I hope this helps.

react-router v4 : how do you handle "/" page as synonym for other page?

I have a server that renders the same single page app for multiple URLS :
/
/A
/B
I want A to act as a "Home" page.
So a browser request to "/" or "/A" should display the same thing.
In particular, I'll have links to pages A and B, and I want the link to A to be marked as active for "/" and "/A".
So I'm using something like :
<NavLink to="/A" activeClassName='nav-active'>Go to A</NavLink>
<NavLink to="/B" activeClassName='nav-active'>Go to B</NavLink>
<Router>
<Route path='/A' component={A} />
<Route path='/B' component={B} />
</Router>
How would I make "/" as a synonym for "/A" ? What I tried :
adding another Route with path="/" : this results in two components being displayed
using a regexp like path="/(A)?" : this displays the right component, but the link ist not marked as active
Should I implement it as a server side redirect instead (just making / redirect to /A rather than serving the same page content ?)
It seems like a Redirect does the trick
<Router>
<Route path='/A' component={A} />
<Route path='/B' component={B} />
<Route path='/' render={() => (
<Redirect to='/A' />
)} />
</Router>
You can add exact={true}
<Router>
<Route path='/' exact={true} component={A} />
<Route path='/A' exact={true} component={A} />
<Route path='/B' exact={true} component={B} />
</Router>