1

I'm currently developing a app in which we have a feature called "tips" which are essentially microblogs. In these blogs which are html based you can link to other "Content" that exists on our app through ordinary hyperlinks.

The app is set up to open the url scheme of these links and all platforms have their own code to funnel the new uri into the xamarin forms app via the MessagingCenter which has a subcriber inside of the App class like this:

 MessagingCenter.Subscribe(Current, DoshiMessages.NewUri, async (Application app, string uri) =>
 {
     var result = await HandleUriNavAsync(uri);

     if (!result)
        await Container.Resolve<IUserDialogs>().AlertAsync("Link was invalid");
 });

Which calls:

    private async Task<bool> HandleUriNavAsync(string uri)
    {
        if (uri == null)
            return false;

        await NavigationService.NavigateAsync(new Uri(uri, UriKind.Absolute));
        return true;
    }

Now this works fine with absolute uri's but if i change it to

        //Example: uri = www.example.com/main/nav/test?userid=0
    private async Task<bool> HandleUriNavAsync(string uri)
    {
        if (uri == null)
            return false;

        //Example: relative = test?userid=0
        var relative = uri.Split('/').Last();
        await NavigationService.NavigateAsync(new Uri(relative, UriKind.Relative));
        return true;
    }

Navigation never triggers but no exceptions are thrown and the task finishes successfully(I have checked). Note the above code is executed while the app is already running and already has active viewmodels.

Is there something obvious I'm doing wrong and is there a better way of achieving this?

Cheers!

scottyaim
  • 71
  • 1
  • 7
  • A few more detail questions... 1. How did you get the NavigationService instance in the HandleUriNavAsync? 2. Can this navigation trigger be done anywhere in the app? So no matter what screen you are currently on ( in other words no matter what the current navigation path is? ) – Depechie Mar 07 '19 at 12:36
  • @Depechie the NavigationService is a Property of the PrismApplication class which i base my App class on. HandleUriNavAsync is a method in my app class. Navigation with an absolute Uri seems to work everywhere but I've only managed to get relative uris working from the currently active viewmoddel – scottyaim Mar 07 '19 at 17:46
  • In general you need to use the one that has been ioc’ed in the VM because PRISM keeps track of other stuff for correct navigation – Depechie Mar 07 '19 at 17:49
  • @Depechie i see maybe If i resolve a new instance from the Container in my app class it will work. – scottyaim Mar 07 '19 at 17:51
  • Than the second part of my q is important, not all navigation will work straight away. Depends if a model page is open or not and other stuff. In general for PRISM if you want to renew the complete nav stack the URL should start with a / – Depechie Mar 07 '19 at 17:53
  • @Depechie i understand. I don't make use of any modal navigation in my app so that should be fine. Yes I'm aware that but i would rather like to navigate relativly from the current page as it does not disrupt the flow of my app. – scottyaim Mar 07 '19 at 18:00

2 Answers2

0

I test your code and get the result like the following screenshot, this issue is related to the uri type.

You have set the UriKind.Absolute, so you uri type should be www.example.com/main/nav/test?userid=0.

If you set the UriKind.Relative, after spliting uri, this type of uri could be setted.

In the end, No exceptions are thrown in VS, that's so wired. enter image description here

Leon
  • 8,404
  • 2
  • 9
  • 52
  • Hi thanks for your answer. My bad i forgot to change the UriKind to Relative in the last example it was meant to be Relative. I have edited my question. – scottyaim Mar 07 '19 at 10:13
0

So i ended up with a workaround which works pretty good. It's a bit sketchy but because all my viewmodels inherit a common base class i can get the current viewmodel with some help of Prism PageUtils

MessagingCenter.Subscribe(Current, DoshiMessages.NewUri, async (Application app, string uri) =>
{
    try
    {
        var relative = uri.Split('/').LastOrDefault();

        if(relative != null)
        {
            var currentVM = PageUtilities.GetCurrentPage(MainPage).BindingContext as ViewModelBase;
            await currentVM.HandleNewUriAsync(relative);
        }
    }
    catch(Exception ex)
    {
       Crashes.TrackError(ex);
    }
});

And then just perform the navigation in the current viewmodel

    public async Task HandleNewUriAsync(string uri)
    {
        await _navigationService.NavigateAsync(new Uri(uri, UriKind.Relative));
    }
scottyaim
  • 71
  • 1
  • 7