skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    Okay with few tweaks 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 UnauthorizedLayout I have this:

    @inherits LayoutComponentBase
    
    <div class="MainBody">
      <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.


  2. 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 class="text-center">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...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search