Upgrade to Prism 8 is causing navigation errors

Viewed 728

Environment

  • Xamarin Forms: 5.0.0.1709-pre4 (but also fails with 4.8.0.1687)
  • VS2019 16.8.3
  • XCode: 12.2

Prism NuGets

  • Prism.DryIoc.Extensions 8.0.48
  • Prism.Forms 8.0.0.1909
  • Prism.PluginPopups 8.0.31-beta
  • Shiny.Prism 8.0.48

Inner Exception from INavigationResult: DryIoc.ContainerException -> InvalidOperationException

    code: Error.UnableToResolveFromRegisteredServices;
    message: Unable to resolve Resolution root IRMobile.PageModels.LandingPageModel with passed arguments 
    [Constant(Prism.Navigation.ErrorReportingNavigationService, 
    typeof(Prism.Navigation.ErrorReportingNavigationService))]
      from container with scope {Name=null}
     with Rules with {TrackingDisposableTransients, UseDynamicRegistrationsAsFallbackOnly, 
    FuncAndLazyWithoutRegistration, SelectLastRegisteredFactory} and without 
    {ThrowOnRegisteringDisposableTransient, UseFastExpressionCompilerIfPlatformSupported}
     with FactorySelector=SelectLastRegisteredFactory
     with Made={FactoryMethod=ConstructorWithResolvableArguments}
      with normal and dynamic registrations:
      (DefaultDynamicKey(0), {FactoryID=317, ImplType=IRMobile.PageModels.LandingPageModel, 
    Reuse=TransientReuse, HasCondition})

Stack Trace from InnerException:

  at DryIoc.Container.TryThrowUnableToResolve (DryIoc.Request request) [0x00058] in /_/src/DryIoc/Container.cs:1077 
  at DryIoc.Container.DryIoc.IContainer.ResolveFactory (DryIoc.Request request) [0x00072] in /_/src/DryIoc/Container.cs:1059 
  at DryIoc.Container.ResolveAndCacheKeyed (System.Int32 serviceTypeHash, System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Object scopeName, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x000c5] in /_/src/DryIoc/Container.cs:471 
  at DryIoc.Container.DryIoc.IResolver.Resolve (System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x00042] in /_/src/DryIoc/Container.cs:430 
  at DryIoc.Resolver.Resolve (DryIoc.IResolver resolver, System.Type serviceType, System.Object[] args, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, System.Object serviceKey) [0x00000] in /_/src/DryIoc/Container.cs:7809 
  at Prism.DryIoc.DryIocContainerExtension.Resolve (System.Type type, System.ValueTuple`2[System.Type,System.Object][] parameters) [0x0001c] in /_/external/Prism/src/Containers/Prism.DryIoc.Shared/DryIocContainerExtension.cs:294 

App.xaml.cs

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // for RgPopups
            containerRegistry.RegisterPopupNavigationService();
            containerRegistry.RegisterPopupDialogService();

            // Essentials
            containerRegistry.Register<ISecureStorage, SecureStorageImplementation>();
            containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();

            // page stuff
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<IconNavigationPage>();
            containerRegistry.RegisterSingleton<IPageBehaviorFactory, CustomPageBehaviorFactory>();

            ...
            // Page and model registrations
containerRegistry.RegisterForNavigation<LoginPage, LoginPageModel>();
            containerRegistry.RegisterForNavigation<LandingPage, LandingPageModel>();

        }

I get this exeption when trying to navigate to a root master/detail page from a LoginPage

await NavigationService.NavigateAsync("/MainPage/NavigationPage/LandingPage")

and the constructor for the LandingPage is

public LandingPageModel(INavigationService navigationService, IMapper mapper, IDialogs dialogs, IPushManager pushManager) : base(navigationService, mapper)

I am fairly new to Prism so I'm sure I am missing something, a registration or maybe a NuGet package, but I'm not sure what it would be. I commented out the Registrations for Popup as I was getting the same error, but referring to Prism.Plugin.Popups.PopupPageNavigationService

As always, thanks for any help!

1 Answers

It looks like you are attempting to navigate to a page called LandingPage, but you haven't told the container what LandingPage is.

Every time you want to create a new view and navigate to it, you need to register it for Navigation inside your App.Xaml.cs file;

containerRegistry.RegisterForNavigation<LandingPage, LandingPageViewModel>();

This line registers the view and its corresponding ViewModel inside the container. Once the container knows about the view, the NavigationService can resolve the view you wish to navigate to using the literal name of the view LandingPage.

Now you can call

await NavigationService.NavigateAsync("LandingPage");
//or
await NavigationService.NavigateAsync("/MainPage/NavigationPage/LandingPage")

NOTE

Prism navigation has a couple of neat tricks built into it. It is Uri based, so every time you navigate to another view, passing the name of the view in the NavigateAsync method will stack the view on top of the others. This means that if you start at the URI NavigationPage/PageA, if you then say NavigateAsync("PageB") you will end up at NavigationPage/PageA/PageB.

Additionally, including the / character at the very beginning of the NavigateAsync argument completely resets the stack. So if you navigate to /PageC from NavigationPage/PageA/PageB, this resets the stack to just PageC

Related