{"id":1872,"date":"2026-07-28T13:00:00","date_gmt":"2026-07-28T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1872"},"modified":"2026-03-07T03:50:15","modified_gmt":"2026-03-07T08:50:15","slug":"xamarin-deep-linking","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/xamarin-deep-linking\/","title":{"rendered":"Xamarin Deep Linking: Cross-Platform Setup"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Xamarin and .NET MAUI apps share C# business logic across platforms but require platform-specific configuration for deep linking. The verification files (AASA, assetlinks.json), entitlements, and Intent filters are native concerns. The URL routing logic can be shared.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For Kotlin Multiplatform deep linking, see <a href=\"https:\/\/tolinku.com\/blog\/kotlin-multiplatform-deep-links\/\">Kotlin Multiplatform deep links<\/a>. For the cross-platform overview, see <a href=\"https:\/\/tolinku.com\/blog\/cross-platform-deep-linking-guide\/\">cross-platform deep linking guide for 2026<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">.NET MAUI Setup (Recommended)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">.NET MAUI is the successor to Xamarin.Forms. If you are starting a new project, use MAUI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">iOS Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Add Associated Domains<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In your MAUI project, add the entitlement in <code>Platforms\/iOS\/Entitlements.plist<\/code>:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;!DOCTYPE plist PUBLIC &quot;-\/\/Apple\/\/DTD PLIST 1.0\/\/EN&quot; &quot;http:\/\/www.apple.com\/DTDs\/PropertyList-1.0.dtd&quot;&gt;\n&lt;plist version=&quot;1.0&quot;&gt;\n&lt;dict&gt;\n    &lt;key&gt;com.apple.developer.associated-domains&lt;\/key&gt;\n    &lt;array&gt;\n        &lt;string&gt;applinks:yourdomain.com&lt;\/string&gt;\n    &lt;\/array&gt;\n&lt;\/dict&gt;\n&lt;\/plist&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Handle Universal Links in AppDelegate<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <code>Platforms\/iOS\/AppDelegate.cs<\/code>:<\/p>\n\n\n\n<pre><code class=\"language-csharp\">[Export(&quot;application:continueUserActivity:restorationHandler:&quot;)]\npublic bool ContinueUserActivity(\n    UIApplication application,\n    NSUserActivity userActivity,\n    UIApplicationRestorationHandler completionHandler)\n{\n    if (userActivity.ActivityType == NSUserActivityType.BrowsingWeb\n        &amp;&amp; userActivity.WebPageUrl != null)\n    {\n        var url = userActivity.WebPageUrl.ToString();\n        DeepLinkHandler.HandleUrl(url);\n        return true;\n    }\n    return false;\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Android Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Add Intent Filters<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <code>Platforms\/Android\/AndroidManifest.xml<\/code>:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;activity android:name=&quot;.MainActivity&quot; android:exported=&quot;true&quot;&gt;\n    &lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n        &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n        &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n        &lt;data android:scheme=&quot;https&quot;\n              android:host=&quot;yourdomain.com&quot;\n              android:pathPrefix=&quot;\/products&quot; \/&gt;\n        &lt;data android:scheme=&quot;https&quot;\n              android:host=&quot;yourdomain.com&quot;\n              android:pathPrefix=&quot;\/offers&quot; \/&gt;\n    &lt;\/intent-filter&gt;\n&lt;\/activity&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or use the <code>IntentFilter<\/code> attribute on your MainActivity:<\/p>\n\n\n\n<pre><code class=\"language-csharp\">[Activity(Theme = &quot;@style\/Maui.SplashTheme&quot;, MainLauncher = true, Exported = true)]\n[IntentFilter(\n    new[] { Intent.ActionView },\n    Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },\n    DataScheme = &quot;https&quot;,\n    DataHost = &quot;yourdomain.com&quot;,\n    DataPathPrefix = &quot;\/products&quot;,\n    AutoVerify = true)]\npublic class MainActivity : MauiAppCompatActivity\n{\n    protected override void OnNewIntent(Intent intent)\n    {\n        base.OnNewIntent(intent);\n        if (intent?.Data != null)\n        {\n            DeepLinkHandler.HandleUrl(intent.Data.ToString());\n        }\n    }\n\n    protected override void OnCreate(Bundle savedInstanceState)\n    {\n        base.OnCreate(savedInstanceState);\n        if (Intent?.Data != null)\n        {\n            DeepLinkHandler.HandleUrl(Intent.Data.ToString());\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Shared Routing Logic<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Deep Link Router (Shared Code)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a shared deep link handler that works on both platforms:<\/p>\n\n\n\n<pre><code class=\"language-csharp\">\/\/ DeepLinkHandler.cs (shared project)\npublic static class DeepLinkHandler\n{\n    public static void HandleUrl(string urlString)\n    {\n        if (!Uri.TryCreate(urlString, UriKind.Absolute, out var uri))\n            return;\n\n        var path = uri.AbsolutePath;\n        var query = System.Web.HttpUtility.ParseQueryString(uri.Query);\n\n        \/\/ Match routes\n        if (TryMatch(path, &quot;\/products\/{0}&quot;, out var productId))\n        {\n            NavigateToProduct(productId, query);\n            return;\n        }\n\n        if (TryMatch(path, &quot;\/offers\/{0}&quot;, out var offerId))\n        {\n            NavigateToOffer(offerId, query);\n            return;\n        }\n\n        if (TryMatch(path, &quot;\/referral\/{0}&quot;, out var referrerId))\n        {\n            NavigateToReferral(referrerId, query);\n            return;\n        }\n\n        \/\/ Default\n        NavigateToHome();\n    }\n\n    private static bool TryMatch(string path, string pattern, out string param)\n    {\n        param = null;\n        var prefix = pattern.Replace(&quot;{0}&quot;, &quot;&quot;);\n        if (!path.StartsWith(prefix)) return false;\n\n        param = path.Substring(prefix.Length).TrimEnd(&#39;\/&#39;);\n        return !string.IsNullOrEmpty(param);\n    }\n\n    private static async void NavigateToProduct(string productId, NameValueCollection query)\n    {\n        await Shell.Current.GoToAsync($&quot;\/\/products\/{productId}&quot;);\n    }\n\n    private static async void NavigateToOffer(string offerId, NameValueCollection query)\n    {\n        await Shell.Current.GoToAsync($&quot;\/\/offers\/{offerId}&quot;);\n    }\n\n    private static async void NavigateToReferral(string referrerId, NameValueCollection query)\n    {\n        await Shell.Current.GoToAsync($&quot;\/\/referral\/{referrerId}&quot;);\n    }\n\n    private static async void NavigateToHome()\n    {\n        await Shell.Current.GoToAsync(&quot;\/\/home&quot;);\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">With Shell Navigation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">.NET MAUI Shell provides built-in route registration:<\/p>\n\n\n\n<pre><code class=\"language-csharp\">\/\/ AppShell.xaml.cs\npublic partial class AppShell : Shell\n{\n    public AppShell()\n    {\n        InitializeComponent();\n\n        \/\/ Register routes for deep linking\n        Routing.RegisterRoute(&quot;products&quot;, typeof(ProductPage));\n        Routing.RegisterRoute(&quot;offers&quot;, typeof(OfferPage));\n        Routing.RegisterRoute(&quot;referral&quot;, typeof(ReferralPage));\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Query Parameter Handling<\/h3>\n\n\n\n<pre><code class=\"language-csharp\">\/\/ ProductPage.xaml.cs\n[QueryProperty(nameof(ProductId), &quot;productId&quot;)]\n[QueryProperty(nameof(Source), &quot;source&quot;)]\npublic partial class ProductPage : ContentPage\n{\n    public string ProductId { get; set; }\n    public string Source { get; set; }\n\n    protected override void OnAppearing()\n    {\n        base.OnAppearing();\n        LoadProduct(ProductId);\n\n        \/\/ Track attribution\n        if (!string.IsNullOrEmpty(Source))\n        {\n            Analytics.TrackDeepLink(Source, $&quot;\/products\/{ProductId}&quot;);\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Xamarin.Forms (Legacy)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you are still on Xamarin.Forms (end of support: May 2024, extended support varies), the approach is similar but uses Xamarin-specific APIs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">iOS (Xamarin.iOS)<\/h3>\n\n\n\n<pre><code class=\"language-csharp\">\/\/ AppDelegate.cs\npublic override bool ContinueUserActivity(\n    UIApplication application,\n    NSUserActivity userActivity,\n    UIApplicationRestorationHandler completionHandler)\n{\n    if (userActivity.WebPageUrl != null)\n    {\n        DeepLinkHandler.HandleUrl(userActivity.WebPageUrl.ToString());\n        return true;\n    }\n    return false;\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Android (Xamarin.Android)<\/h3>\n\n\n\n<pre><code class=\"language-csharp\">[Activity(MainLauncher = true)]\n[IntentFilter(new[] { Intent.ActionView },\n    Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },\n    DataScheme = &quot;https&quot;,\n    DataHost = &quot;yourdomain.com&quot;,\n    AutoVerify = true)]\npublic class MainActivity : FormsAppCompatActivity\n{\n    protected override void OnCreate(Bundle savedInstanceState)\n    {\n        base.OnCreate(savedInstanceState);\n        if (Intent?.Data != null)\n        {\n            DeepLinkHandler.HandleUrl(Intent.Data.ToString());\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">iOS Simulator<\/h3>\n\n\n\n<pre><code class=\"language-bash\">xcrun simctl openurl booted &quot;https:\/\/yourdomain.com\/products\/abc123&quot;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Android Emulator<\/h3>\n\n\n\n<pre><code class=\"language-bash\">adb shell am start -a android.intent.action.VIEW \\\n  -d &quot;https:\/\/yourdomain.com\/products\/abc123&quot; \\\n  -c android.intent.category.BROWSABLE\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Unit Testing the Router<\/h3>\n\n\n\n<pre><code class=\"language-csharp\">[Test]\npublic void HandleUrl_ProductLink_NavigatesToProduct()\n{\n    var url = &quot;https:\/\/yourdomain.com\/products\/abc123?ref=email&quot;;\n    \/\/ Test that the routing logic correctly parses the URL\n    var result = DeepLinkRouter.Parse(url);\n    Assert.AreEqual(&quot;ProductPage&quot;, result.Screen);\n    Assert.AreEqual(&quot;abc123&quot;, result.Params[&quot;productId&quot;]);\n    Assert.AreEqual(&quot;email&quot;, result.Query[&quot;ref&quot;]);\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Tolinku for .NET Apps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/tolinku.com\/features\/deep-linking\">Tolinku<\/a> hosts AASA and assetlinks.json files, handles deferred deep links, and provides analytics. See the <a href=\"https:\/\/tolinku.com\/docs\/concepts\/deep-linking\/\">deep linking documentation<\/a> for integration details.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For implementation from scratch, see <a href=\"https:\/\/tolinku.com\/blog\/implement-deep-links-from-scratch\/\">how to implement deep links from scratch<\/a>. For the full guide, see <a href=\"https:\/\/tolinku.com\/blog\/cross-platform-deep-linking-guide\/\">cross-platform deep linking guide for 2026<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Implement deep linking in Xamarin and .NET MAUI apps. Handle platform-specific configuration and shared deep link routing logic.<\/p>\n","protected":false},"author":2,"featured_media":1871,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Xamarin Deep Linking: Cross-Platform Setup","rank_math_description":"Implement deep linking in Xamarin and .NET MAUI apps. Handle platform-specific configuration and shared deep link routing logic.","rank_math_focus_keyword":"Xamarin deep linking","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-xamarin-deep-linking.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-xamarin-deep-linking.png","footnotes":""},"categories":[15],"tags":[23,156,567,20,566,69,22,565],"class_list":["post-1872","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-app-links","tag-cross-platform","tag-csharp","tag-deep-linking","tag-dotnet-maui","tag-mobile-development","tag-universal-links","tag-xamarin"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1872","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1872"}],"version-history":[{"count":1,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1872\/revisions"}],"predecessor-version":[{"id":1873,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1872\/revisions\/1873"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1871"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1872"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1872"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1872"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}