Shell Navigation errors

Eduardo Gomez 3,416 Reputation points
2024-03-12T01:40:29.9166667+00:00

I have my shell.

<ShellContent
    ContentTemplate="{DataTemplate pages:StartupPage}"
    Route="StartupPage"
    Shell.FlyoutBehavior="Disabled"
    Shell.FlyoutItemIsVisible="False" />
<ShellContent
    ContentTemplate="{DataTemplate pages:LoginPage}"
    Route="LoginPage"
    Shell.FlyoutBehavior="Disabled"
    Shell.FlyoutItemIsVisible="False" />
<ShellContent
    ContentTemplate="{DataTemplate pages:NoInternetPage}"
    Route="NoInternetPage"
    Shell.FlyoutBehavior="Disabled"
    Shell.FlyoutItemIsVisible="False" />
<ShellContent
    ContentTemplate="{DataTemplate pages:RoleSelectionPage}"
    Route="RoleSelectionPage"
    Shell.FlyoutBehavior="Disabled"
    Shell.FlyoutItemIsVisible="False" />
   
<Shell.FlyoutFooterTemplate>
    <DataTemplate>
        <Button
            Margin="20"
            Command="{Binding SignOutCommand}"
            CornerRadius="8"
            Text="Log out" />
    </DataTemplate>
</Shell.FlyoutFooterTemplate>



and the firs page that comes up, is the startupPage,this is where I check if the user is authenticated or not and if we have internet,

Also, I created a helped method, to create my flyout page (Since I cannot do it on the fly)

    public static void CreateFlyoutMenu(string role) {
        switch(role) {
            case nameof(Role.Student):
                CreateStudentItems();
                break;
            case nameof(Role.Teacher):
                CreateTeacherItems();
                break;
            case nameof(Role.Coordinator):
                CreateCoordintorItems();
                break;
        }
    }
    private static void CreateStudentItems() {
        var studentItems = new FlyoutItem() {
            Title = "Welcome",
            Route = nameof(WelcomePage),
            FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems,
            Items = {
                 new ShellContent {
                     Title = "Welcome",
                     ContentTemplate = new DataTemplate(typeof(WelcomePage)),
                 },
                 new ShellContent {
                     Title = "Join meeting",
                     ContentTemplate = new DataTemplate(typeof(JoinMeetingPage)),
                 }
            }
        };
        Shell.Current.Items.Add(studentItems);
    }
    private static void CreateTeacherItems() {
        var TeacherItems = new FlyoutItem() {
            Title = "Welcome",
            Route = nameof(WelcomePage),
            FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems,
            Items = {
                 new ShellContent {
                     Title = "Welcome",
                     ContentTemplate = new DataTemplate(typeof(WelcomePage)),
                 },
                 new ShellContent {
                     Title = "My courses",
                     ContentTemplate = new DataTemplate(typeof(NotificationsPage)),
                 },
                 new ShellContent {
                     Title = "New lecture",
                     ContentTemplate = new DataTemplate (typeof(NewLecturePage)),
                 },
                 new ShellContent {
                     Title = "New Test",
                     ContentTemplate = new DataTemplate(typeof(NewTestPage)),
                 },
                 new ShellContent {
                     Title = "Schedule lecture",
                     ContentTemplate = new DataTemplate (typeof(NewLecturePage)),
                 },
                 new ShellContent {
                     Title = "Schedule test",
                     ContentTemplate = new DataTemplate(typeof(ScheduleTestPage)),
                 },
            }
        };
        Shell.Current.Items.Add(TeacherItems);
    }
    private static void CreateCoordintorItems() {
        var CoordinatorItems = new FlyoutItem() {
            Title = "Welcome",
            Route = nameof(WelcomePage),
            FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems,
            Items = {
                new ShellContent {
                    Title = "Welcome",
                    ContentTemplate = new DataTemplate(typeof(WelcomePage)),
                },
                new ShellContent {
                    Title = "Manage courses",
                    ContentTemplate = new DataTemplate(typeof(ManageCoursePage)),
                },
                new ShellContent {
                    Title = "Register student",
                    ContentTemplate = new DataTemplate(typeof(RegisterStudentPage)),
                }
            }
        };
        Shell.Current.Items.Add(CoordinatorItems);
    }
}
private async void CheckAuth() {
    var currentUserAsJson = await SecureStorage.GetAsync(Constants.LOGGED_USER);
    if(string.IsNullOrEmpty(currentUserAsJson)) {
        if(DeviceInfo.Platform == DevicePlatform.WinUI) {
            Shell.Current.Dispatcher.Dispatch(async () => {
                await Shell.Current.GoToAsync($"//{nameof(LoginPage)}", true);
            });
        } else {
            await Shell.Current.GoToAsync($"//{nameof(LoginPage)}", true);
        }
    } else {
        var loggedUser = await StorageHelper<DemyUser>.GetJsonFromStorageAsync(currentUserAsJson);
        FlyoutHelper.CreateFlyoutHeader(loggedUser);
        FlyoutItemCreator.CreateFlyoutMenu(loggedUser?.CurrentRole!);
        await Shell.Current.GoToAsync($"//{nameof(WelcomePage)}", true);
    }


The first time I rung the app, I go to the login screen, to create my account.

  async Task Login() {
      IsBusy = true;
      var user = await authenticationService.LoginWithEmailAndPassword("a@a.com", "123456");
      if(user is not null) {
          await appService.NavigateTo($"//{nameof(RoleSelectionPage)}", true);
      }
      IsBusy = false;


When I create an account, I have to select my role

public RoleSelectionPageViewModel(IAuthenticationService authService,
    IDataService<DemyUser> dataService, IAppService appService) {
    _authService = authService;
    _dataService = dataService;
    _appService = appService;
    InitPopUp();
}
private async void InitPopUp() {
    Roles = GetRoles();
    fireUser = await _authService.GetLoggedInUser();
    WelcomeText = $"Welcome {fireUser?.Info.DisplayName}, please chose a role";
}
[RelayCommand]
public void RoleSelected(UserRoles SelectedRole) {
    foreach(var role in Roles!) {
        role.IsSelected = role == SelectedRole; // Set IsSelected to true only for the selected rol
        if(role.IsSelected) {
            role.SelectedColor = UserRoles.RoleSelectedColor;
        } else {
            role.SelectedColor = UserRoles.DefaultUnselectedColor;
        }
    }
    selectedRole = SelectedRole.Name.ToString();
}
[RelayCommand]
public async Task UpdateUserCurrentRole() {
    var currentUser = await _dataService.GetByEmailAsync<DemyUser>("Users", fireUser!.Info.Email);
    if(currentUser is not null) {
        currentUser.Roles ??= [];
        currentUser.CurrentRole = selectedRole;
        if(!currentUser.Roles.Contains(selectedRole!)) {
            currentUser.Roles.Add(selectedRole!);
        }
        await _dataService.UpdateAsync("Users", currentUser.Uid!, currentUser);
    }
    var updatedUser = await _dataService.GetByEmailAsync<DemyUser>("Users", fireUser!.Info.Email);
    FlyoutHelper.CreateFlyoutHeader(updatedUser);
    var cuurentUserAsJson = JsonSerializer.Serialize(currentUser);
    await SecureStorage.SetAsync(Constants.LOGGED_USER, cuurentUserAsJson);
    FlyoutItemCreator.CreateFlyoutMenu(updatedUser?.CurrentRole!);
    await _appService.NavigateTo($"//{nameof(WelcomePage)}", true);
}


and finally, I get into the welcome page, with my customize flyout items

User's image

the problem comes, when I log out.

ApShellViewModel

  [RelayCommand]
  async Task SignOut() {
      SecureStorage.Default.RemoveAll();
      await appService.NavigateTo($"//{nameof(LoginPage)}", true);
  }


when I log out and log back in and select a new role, when I try to navigate, I get the error

Name Value Type
$exception {"Ambiguous routes matched for: //WelcomePage matches found: //WelcomePage,//WelcomePage (Parameter 'uri')"} System.ArgumentException

demo:

https://reccloud.com/u/itveaz1

app, for reference

https://www.dropbox.com/scl/fi/q041gzj04m2g93yud4g1b/DemyAI.zip?rlkey=bbkwtr1nrfjev5j097mv3gbkv&dl=0

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
2,819 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 67,631 Reputation points Microsoft Vendor
    2024-03-12T06:01:26.6133333+00:00

    Hello,

    Ambiguous routes matched for: //WelcomePage matches found: //WelcomePage,//WelcomePage (Parameter 'uri')"

    This occurs when you register your routes in XAML (in the appshell file) and also register your routes in code behind in FlyoutItemCreator.cs. Only register your routes once using either XAML or FlyoutItemCreator.cs not both.

    If you want to register both of two places, you need to change other route name, such as, please open your FlyoutItemCreator.cs to find CreateStudentItems , CreateTeacherItems and CreateCoordintorItems, change all Route to Route = "WelcomePagetab".

    After that, you will get invalid-routes error, please open your StartupPageViewModel.cs and find CheckAuth method. Change navigate to the welcome page code to await Shell.Current.GoToAsync($"{nameof(WelcomePage)}", true);

    And please open your RoleSelectionPageViewModel.cs and find UpdateUserCurrentRole method. Change navigate to the welcome page code to await Shell.Current.GoToAsync($"{nameof(WelcomePage)}", true); as well.

    In the end, you will get the back arrow in your top-left corner. Please add following code to hide the back arrow in welcomepage.xaml

    <ContentPage
        x:Class="DemyAI.Views.WelcomePage"
        xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:vm="clr-namespace:DemyAI.ViewModels"
        x:DataType="vm:WelcomePageViewModel">
    <Shell.BackButtonBehavior>
    <BackButtonBehavior IsVisible="False"
                                />
    </Shell.BackButtonBehavior>
    

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful