I have App.razor file looking like this:
@using MyFirstServerSideBlazor.Pages
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeView>
<Authorized>
<RouteView DefaultLayout="@typeof(MainHeaderLayout)" RouteData="@routeData" />
</Authorized>
<NotAuthorized>
<RouteView DefaultLayout="@typeof(LoginBody)" RouteData="@routeData" />
</NotAuthorized>
</AuthorizeView>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<p role="alert">Sorry, there's nothing at this address.</p>
</NotFound>
</Router>
</CascadingAuthenticationState>
Is there some way I can specify what routes I want to show, for Unauthenticated user ?
Lets say I want to let Unauthenticated users to navigate to /Login & /SignUp pages. I could probable use attributes or something on pages to specify that only authenticated user can view them, but this seems to be inconvenient. I'm wondering is there some better solution ?
I could also make component that shows different pages, but Im unable to change URI routes that way, example would be:
<NotAuthorized>
<ComponentForUnauthorizedUsers/>
</NotAuthorized>
And then in that component have some logic like this:
@using MyFirstServerSideBlazor.Componenets.Forms
@inject NavigationManager navigation
@{
if (ShowLogin)
{
<PageTitle>Login</PageTitle>
}
else
{
<PageTitle>Sign Up</PageTitle>
}
}
@{
if (ShowLogin)
{
<LoginForm ChangePageCallback="ChangeToSignUp"/>
}
else
{
<SignUpComponent ChangePageCallback="ChangeToLogin"/>
}
}
@code{
public bool ShowLogin { get; set; } = true;
public void ChangeToSignUp()
{
ShowLogin = false;
StateHasChanged();
}
public void ChangeToLogin()
{
ShowLogin = true;
StateHasChanged();
}
}
this also seems wrong, and this way I cannot use Routing.
CodePudding user response:
There's a handful of options here and I wish I knew the best one myself. Here's what I'm currently doing in my app:
App.Razor
@inject NavigationManager nav
<CascadingAuthenticationState>
<AuthorizeView>
<NotAuthorized>
@{
/* THE IMPORTANT PART TO REDIRECT AWAY FROM UNAUTHORIZED PAGES */
if (new Uri(nav.Uri).AbsolutePath.StartsWith("/login") == false)
nav.NavigateTo($"/login/{System.Web.HttpUtility.UrlEncode(new Uri(nav.Uri).PathAndQuery)}");
}
</NotAuthorized>
</AuthorizeView>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
<RequestCardTemplate Title="Loading...">
<Body>
Loading...
</Body>
</RequestCardTemplate>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<h1 >Sorry, there's nothing at this address.</h1>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Deciding which pages require auth
If a page does not require authorization, then I just write the page as normal. If it does require authorization, then I drop the Authorize attribute into the MyPage.razor
file.
@page "/mypage"
@attribute [Authorize]
@* Rest of page stuff *@
Different components
As you mentioned, you can show different links or something if you want to based on whether a user is logged in (authorized?) or not.
@* page stuff... *@
<AuthorizeView>
<Authorized>
<a href="/myaccount">My Account</a>
<a href="/myposts">My Posts</a>
</Authorized>
<NotAuthorized>
<a href="/login">Login</a>
<a href="/signup">Signup</a>
</NotAuthorized>
</AuthorizeView
@* more page stuff...
CodePudding user response:
Okay with few tweaks it I managed to make it Work, In my APP.Razor:
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeView>
<Authorized>
<RouteView DefaultLayout="@typeof(MainHeaderLayout)" RouteData="@routeData" />
</Authorized>
<NotAuthorized>
<UnauthorizedLayout/>
</NotAuthorized>
</AuthorizeView>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<p role="alert">Sorry, there's nothing at this address.</p>
</NotFound>
</Router>
</CascadingAuthenticationState>
Then in Layout I have This:
@inherits LayoutComponentBase
<div >
<UnauthorizedViewControler/>
</div>
In UnauthorizedViewControler component i Have this logic:
@inject NavigationManager navigation
@{
if (ShowLogin)
{
<LoginPage/>
}
else
{
<SignUpPage/>
}
}
@code{
public bool ShowLogin { get; set; } = true;
protected override void OnInitialized()
{
LocationChanged(null,null);
navigation.LocationChanged = LocationChanged;
base.OnInitialized();
}
void LocationChanged(object sender, LocationChangedEventArgs e)
{
if (navigation.Uri.Contains("/signup"))
{
ShowLogin = false;
}
else
{
ShowLogin = true;
}
StateHasChanged();
}
}
And for pages themselves :
// injects & usings...
@layout UnauthorizedLayout
@page "/Login"
// HTML & Code...
,
// injects & usings...
@layout UnauthorizedLayout
@page "/SignUp"
// HTML & Code...
And this works, I have routing for /Login and /SignUp, Code, could use some cleaning up, but in principle this works.