.NET MAUI Deep Linking and URI based Navigation Step by step Implementation and Top 10 Questions and Answers
 Last Update: April 01, 2025      16 mins read      Difficulty-Level: beginner

.NET MAUI Deep Linking and URI-Based Navigation

Deep linking and URI-based navigation are essential features in modern mobile application development allowing users to access specific screens or functionalities directly via a custom URL. In the context of .NET Multi-platform App UI (MAUI), these features enable developers to enhance the user experience by providing seamless navigation through links, improving app engagement, and facilitating better integration with external apps, content, and services.

Understanding Deep Linking

Deep linking refers to the ability to link to a specific screen or a specific piece of content within a mobile app using a URI (Uniform Resource Identifier). Unlike a traditional web link that opens a website, a deep link opens the mobile app directly at a particular location within it. This feature is crucial for several reasons:

  • Seamless Navigation: Users can navigate directly to the desired content, reducing the number of clicks and improving efficiency.
  • Improved Engagement: Custom URLs can be used in marketing campaigns, advertisements, or emails, leading to enhanced user engagement.
  • Simplified Integration: Integration with other services becomes easier as apps can be integrated through specific URLs.

URI-Based Navigation in .NET MAUI

.NET MAUI supports deep linking through URI-based navigation, which allows developers to define routes and handle navigation based on URIs. Here’s a detailed breakdown of how to implement this feature:

Configuring Routes

The first step in setting up URI-based navigation is to configure routes in your application. Routes are essentially mappings between URIs and views or pages within your app.

Example: Configuring a Route

public App()
{
    InitializeComponent();

    // Define the root page with navigation
    MainPage = new NavigationPage(new AppShell());

    // Register routes
    Routing.RegisterRoute(nameof(LoginPage), typeof(LoginPage));
    Routing.RegisterRoute(nameof(ProductDetailPage), typeof(ProductDetailPage));
    Routing.RegisterRoute(nameof(CartPage), typeof(CartPage));
}

In this example, Routing.RegisterRoute is used to map URIs like /LoginPage to specific pages such as LoginPage.

Defining Routes in XAML

Alternatively, you can define routes directly in your XAML file using Shell content.

Example: Defining Routes in XAML

<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       x:Class="MyApp.AppShell">

    <TabBar>
        <ShellContent Route="LoginPage" Title="Login" Icon="login.png">
            <views:LoginPage />
        </ShellContent>
        <ShellContent Route="ProductDetailPage" Title="Product Detail" Icon="product.png">
            <views:ProductDetailPage />
        </ShellContent>
        <ShellContent Route="CartPage" Title="Cart" Icon="cart.png">
            <views:CartPage />
        </ShellContent>
    </TabBar>
</Shell>

This XAML snippet defines routes for the login page, product detail page, and cart page.

Handling Deep Links

To handle deep links, you need to specify the scheme, host, and path that the app should respond to.

Example: Handling Deep Links

protected override void OnRegisterRoutes(IAppHostBuilder builder)
{
    builder
        .ConfigureMauiHandlers(handlers => { })
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        })
        .Configure(app =>
        {
            app.UseRouting();

            // Register routes
            app.MapRoute("loginRoute", "/LoginPage/{userId:object?}",
                builder =>
                {
                    builder.MapHandler(ctx => ctx.Items.Add("targetPage", typeof(LoginPage)));
                });

            app.MapRoute("productRoute", "/ProductDetailPage/{id:object?}",
                builder =>
                {
                    builder.MapHandler(ctx => ctx.Items.Add("targetPage", typeof(ProductDetailPage)));
                });

            app.MapRoute("cartRoute", "/CartPage",
                builder =>
                {
                    builder.MapHandler(ctx => ctx.Items.Add("targetPage", typeof(CartPage)));
                });
        });
}

In this example, deep links are registered with specific patterns (/LoginPage/{userId:object?}, /ProductDetailPage/{id:object?}, and /CartPage). When these URIs are invoked, the corresponding pages are navigated to.

Navigating Using URIs

Once routes are registered, you can navigate to specific pages using URIs.

Example: Navigating Using URIs

await Shell.Current.GoToAsync("LoginPage/user123");
await Shell.Current.GoToAsync("ProductDetailPage/456");
await Shell.Current.GoToAsync("CartPage");

These lines of code navigate the app to the login page for user user123, the product detail page for product 456, and the cart page, respectively.

Custom Handlers and Parameters

Handling complex scenarios often requires custom handlers and parameters.

Example: Custom Handler with Parameters

app.MapRoute("customProductRoute", "/ProductDetailPage/{id:object?}",
    builder =>
    {
        builder.MapHandler(ctx =>
        {
            var id = ctx.GetRouteValue("id") as string;
            var targetPage = typeof(ProductDetailPage);
            ctx.Items.Add("targetPage", targetPage);

            if (targetPage != null)
            {
                var shell = Shell.Current;
                var navigationParam = new Dictionary<string, object>
                {
                    { "productId", id }
                };

                shell.GoToAsync(targetPage.ToString(), navigationParam);
            }
        });
    });

This example demonstrates how to pass parameters (productId) to the target page (ProductDetailPage).

Security Considerations

Security is a critical aspect of deep linking. Ensure that:

  • URIs are well-defined: Only register routes that you intend to handle.
  • Validate input parameters: Always validate and sanitize any input parameters received through deep links.
  • Use HTTPS: When using web-based deep linking, ensure that the scheme is secure (HTTPS).

Conclusion

Deep linking and URI-based navigation are powerful tools in the .NET MAUI framework that facilitate seamless navigation, enhance user experience, and improve engagement. By defining routes, handling URIs, and incorporating best practices for security, developers can effectively leverage these features to create robust and user-friendly mobile applications.

Understanding and implementing deep linking and URI-based navigation in .NET MAUI requires careful planning and configuration, but the benefits outweigh the effort, making it a valuable skill for modern mobile app development.

.NET MAUI Deep Linking and URI-based Navigation: A Step-by-Step Guide for Beginners

Deep linking and URI-based navigation are powerful features in .NET Multi-platform App UI (.NET MAUI) that allow apps to be opened directly to specific content by using URLs. This can enhance user experience, especially when integrating with web applications, sharing links, or handling notifications. In this guide, we will explore how to set up deep linking in .NET MAUI and walk through data flow step-by-step.

Step 1: Setting Up Your .NET MAUI Project

  1. Create a New .NET MAUI Project:

    • Open Visual Studio or Visual Studio Code.
    • Click on Create a new project.
    • Search for .NET MAUI App and choose the appropriate template.
    • Configure your project settings (Name, Location, Solution Name) and click Create.
  2. Install Necessary NuGet Packages (if any):

    • .NET MAUI already has built-in support for navigation and deep linking, so additional NuGet packages are generally not needed for basic use.

Step 2: Define Your Navigation Structure

  1. Create Navigation Pages:

    • Add new XAML pages to your project for different views. For example, you might have HomePage.xaml, DetailsPage.xaml, etc.
    • Each page should have its corresponding code-behind file (e.g., HomePage.xaml.cs).
  2. Set Up Shell for Navigation:

    • .NET MAUI Shell is a modern navigation paradigm that can simplify the navigation structure of your app. To use Shell, create a AppShell.xaml file if not already present.
    • Define routes for your pages in App.xaml.cs:
      public App()
      {
          InitializeComponent();
      
          Routing.RegisterRoute(nameof(DetailsPage), typeof(DetailsPage));
          MainPage = new AppShell();
      }
      

Step 3: Register Deep Links

  1. Define Schemes and Hosts:

    • Choose a unique URL scheme and host for your app. For example, myapp:// or https://myapp.com/.
  2. Configure Deep Linking in Android:

    • In the AndroidManifest.xml file, define an intent filter for your deep link:
      <activity android:name="crc643f460878ebf1c403.MauiAppCompatActivity"
                android:theme="@style/Maui.SplashTheme"
                android:configChanges="fontScale|uiMode|screenSize|smallestScreenSize|screenLayout|orientation"
                android:exported="true">
        <intent-filter android:label="MyApp">
          <action android:name="android.intent.action.VIEW" />
          <category android:name="android.intent.category.DEFAULT" />
          <category android:name="android.intent.category.BROWSABLE" />
          <data android:scheme="myapp" android:host="details" android:pathPrefix="/" />
          <data android:scheme="https" android:host="myapp.com" android:pathPrefix="/details/" />
        </intent-filter>
      </activity>
      
  3. Configure Deep Linking in iOS:

    • In the Info.plist file, define a URL scheme and associated domains:
      <key>CFBundleURLTypes</key>
      <array>
        <dict>
          <key>CFBundleURLName</key>
          <string>com.mycompany.myapp</string>
          <key>CFBundleURLSchemes</key>
          <array>
            <string>myapp</string>
          </array>
        </dict>
      </array>
      <key>LSApplicationQueriesSchemes</key>
      <array>
        <string>https</string>
      </array>
      <key>NSAppTransportSecurity</key>
      <dict>
        <key>NSAllowsArbitraryLoads</key>
        <false/>
      </dict>
      
  4. Configure Deep Linking in Windows:

    • In the Package.appxmanifest file, define a protocol:
      <Extensions>
        <uap:Extension Category="windows.protocol">
          <uap:Protocol Name="myapp">
            <uap:DisplayName>MyApp</uap:DisplayName>
          </uap:Protocol>
        </uap:Extension>
      </Extensions>
      

Step 4: Handling Deep Links in Code

  1. Override the OnAppLinkRequestReceived Method:

    • Handle deep link requests in your App.xaml.cs:
      protected override async void OnAppLinkRequestReceived(Uri uri)
      {
          try
          {
              var route = uri.AbsolutePath.Trim('/');
              await Shell.Current.GoToAsync($"//{route}?param1={uri.Query}");
          }
          catch (Exception ex)
          {
              Console.WriteLine($"Error handling URI: {ex.Message}");
          }
      }
      
  2. Parse Query Parameters:

    • Extract parameters from the URI and use them to load specific data or navigate to a page.

Step 5: Running and Testing

  1. Run Your Application:

    • Build and run your application on your target platform (Android, iOS, or Windows).
  2. Test Deep Links:

    • Open a browser or another app and enter your deep link (e.g., myapp://details?id=123 or https://myapp.com/details?id=123).
    • Verify that the app opens and navigates to the correct page with the appropriate data.

Step 6: Data Flow in Deep Linking

  1. URI Parsing:

    • When a deep link is triggered, the system resolves the URL to your app.
    • The OnAppLinkRequestReceived method processes the URI and extracts path and query parameters.
  2. Navigation Logic:

    • Based on the URI, your app navigates to the appropriate page using Shell.Current.GoToAsync.
    • You can pass parameters to the page using query strings.
  3. Load Data:

    • The target page retrieves parameters from the query string and uses them to fetch and display the specific content.
  4. Enhancements:

    • Implement error handling and logging to manage potential issues.
    • Consider using a service or ViewModel to handle data fetching and state management.

Conclusion

By following these steps, you can set up deep linking and URI-based navigation in your .NET MAUI application. This will enable your app to handle external requests and provide a seamless user experience. Remember to test thoroughly across different devices and platforms to ensure compatibility and stability.

Top 10 Questions and Answers: .NET MAUI Deep Linking and URI-based Navigation

1. What is Deep Linking in .NET MAUI, and why is it essential?

Answer: Deep linking in .NET MAUI allows users to open a specific page or content within a mobile application directly from a URI. This is essential for various reasons, such as improving user experience by taking users directly to the content they are interested in, enhancing app discoverability through search engine optimization, and facilitating integration with other apps and services via URLs.

2. How can I enable deep linking in a .NET MAUI application?

Answer: To enable deep linking in a .NET MAUI application, you need to configure the app's IntentFilter on Android and the LSApplicationQueriesSchemes and CFBundleURLTypes in the Info.plist file for iOS. Additionally, you can use the Shell navigation for URI-based navigation, which simplifies the process. Here’s a basic example for Android:

<activity>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="myapp" android:host="content" />
    </intent-filter>
</activity>

For iOS, you would add similar configurations in Info.plist.

3. Can .NET MAUI support dynamic deep links?

Answer: Yes, .NET MAUI can support dynamic deep links, which can include parameters to pass data to the app. This is useful for creating personalized or context-specific content within your app. To handle parameters in deep links, you can parse the URI in the App.xaml.cs file's OnAppLinkRequestReceived method or by handling the Shell.Current.GoToAsync method if you are using the Shell navigation.

4. How do I handle deep links in a .NET MAUI application?

Answer: Handling deep links in .NET MAUI involves several steps. First, you need to define the deep link schema and configure your app to intercept those URIs. Then, you can handle the URI in the OnAppLinkRequestReceived method in App.xaml.cs for non-Shell apps, or use Shell.Current.GoToAsync within pages for Shell apps. Here’s a basic example using Shell:

protected override async void OnAppLinkRequestReceived(Uri uri)
{
    await Shell.Current.GoToAsync($"//{uri.Host}{uri.PathAndQuery}");
}

5. What are the advantages of using URI-based navigation in .NET MAUI?

Answer: URI-based navigation offers several advantages, including:

  • Clear and consistent navigation: All navigation is based on URIs, making it easier to understand and maintain.
  • Seamless integration: Easier to integrate deep linking, web URLs, and other external navigation methods.
  • Modularity: Promotes modular and testable code by separating navigation logic from the UI.
  • Backward compatibility: Simplifies navigation in large applications and supports backward navigation seamlessly.

6. How do I configure URI-based navigation in .NET MAUI using Shell?

Answer: Configuring URI-based navigation in .NET MAUI using Shell involves defining routes that correspond to your pages. Here’s an example:

<!-- AppShell.xaml -->
<Shell ...>
    <ShellContent Route="home" ContentTemplate="{DataTemplate local:HomePage}" />
    <ShellContent Route="details" ContentTemplate="{DataTemplate local:DetailsPage}" />
</Shell>

In your code, you can then navigate to these pages using:

await Shell.Current.GoToAsync("//home");
await Shell.Current.GoToAsync("//details?id=123");

7. Can I pass parameters with URI-based navigation in .NET MAUI?

Answer: Yes, you can pass parameters with URI-based navigation in .NET MAUI by specifying them in the URI. In your Shell route, you can define a route with parameters, and these can be accessed in the destination page's OnNavigatedTo override. For example:

<!-- AppShell.xaml -->
<ShellContent Route="details/{id}" ContentTemplate="{DataTemplate local:DetailsPage}" />

In DetailsPage.xaml.cs, you can access the parameter like this:

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    if (args.Parameter is string id)
    {
        // Use the id parameter here
    }
}

8. How do I register routes for deep linking outside of Shell in .NET MAUI?

Answer: To register routes for deep linking outside of Shell in .NET MAUI, you can use the Routing.RegisterRoute method in your App.xaml.cs file. Here’s an example:

protected override void OnStart()
{
    Routing.RegisterRoute("home", typeof(HomePage));
    Routing.RegisterRoute("details", typeof(DetailsPage));
    base.OnStart();
}

You can then navigate to these routes using Application.Current.MainPage.Navigation.PushAsync or GoToAsync if you have access to a NavigationPage.

9. How do I handle deep linking when the app is not running?

Answer: When the app is not running, deep links are handled differently depending on the platform. On Android, the app will be started and the deep link will be passed to the OnCreate method of your main activity. On iOS, the app can be started and the deep link will be passed to the AppDelegate's OpenUrl method or ContinueUserActivity method for universal links. You can handle these methods to parse the URI and navigate accordingly.

10. Are there any best practices I should follow when implementing deep linking and URI-based navigation in .NET MAUI?

Answer: Yes, here are some best practices to consider:

  • Define a consistent URI structure: Use a clear and consistent format for your URIs to ensure they are easily understandable and maintainable.
  • Test thoroughly: Test all navigation scenarios, especially when the app is cold-started, to ensure smooth handling of deep links.
  • Handle edge cases: Consider scenarios where the target content might not be available or where the URI format is incorrect, ensuring the app can gracefully handle these situations.
  • Use analytics: Implement analytics to track deep link usage and improve the user experience.
  • Keep routes up to date: Regularly update your route definitions to accommodate changes in your app's structure and content.

By following these guidelines, you can effectively implement deep linking and URI-based navigation in your .NET MAUI application, enhancing its usability and integration capabilities.