From bc43bf9cad02f9bc640121e006b6fb685ad0fa12 Mon Sep 17 00:00:00 2001 From: Shad Storhaug Date: Wed, 11 Jun 2014 02:41:40 +0700 Subject: [PATCH] Fixes #322, using custom URL resolver throws "multiple nodes with same URL" exception. --- .../ISiteMapNodeExtensions.cs | 18 ++++++++++++++++++ .../Matching/SiteMapNodeUrlKey.cs | 16 +++++++++++++++- .../MvcSiteMapProvider.csproj | 1 + .../MvcSiteMapProvider/SiteMap.cs | 8 +------- 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNodeExtensions.cs diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNodeExtensions.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNodeExtensions.cs new file mode 100644 index 00000000..7121bb9d --- /dev/null +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/ISiteMapNodeExtensions.cs @@ -0,0 +1,18 @@ +using System; +using MvcSiteMapProvider.Web.UrlResolver; + +namespace MvcSiteMapProvider +{ + /// + /// Contains extension logic for the ISiteMapNode interface that is not user + /// overridable. + /// + public static class ISiteMapNodeExtensions + { + public static bool UsesDefaultUrlResolver(this ISiteMapNode node) + { + return string.IsNullOrEmpty(node.UrlResolver) || + typeof(SiteMapNodeUrlResolver).Equals(Type.GetType(node.UrlResolver, false)); + } + } +} diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/Matching/SiteMapNodeUrlKey.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/Matching/SiteMapNodeUrlKey.cs index a73e25c9..646b8aa9 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/Matching/SiteMapNodeUrlKey.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/Matching/SiteMapNodeUrlKey.cs @@ -23,7 +23,21 @@ IUrlPath urlPath // Host name in absolute URL overrides this one. this.hostName = node.HostName; - this.SetUrlValues(node.UnresolvedUrl); + + // Fixes #322 - If using a custom URL resolver, we need to account for the case that + // the URL will be provided by the resolver instead of specified explicitly. + if (!string.IsNullOrEmpty(node.UnresolvedUrl)) + { + this.SetUrlValues(node.UnresolvedUrl); + } + else if (!node.UsesDefaultUrlResolver()) + { + // For a custom URL resolver, if the unresolved URL property + // is not set use the one returned from the URL resolver. + // This ensures URLs that are unidentifiable by MVC can still + // be matched by URL. + this.SetUrlValues(node.Url); + } } private readonly ISiteMapNode node; diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj index 0b9852b2..840e9c59 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/MvcSiteMapProvider.csproj @@ -198,6 +198,7 @@ + diff --git a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs index 3e6f6003..f3acfb32 100644 --- a/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs +++ b/src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs @@ -134,7 +134,7 @@ protected virtual void AddNodeInternal(ISiteMapNode node, ISiteMapNode parentNod lock (this.synclock) { IUrlKey url = null; - bool isMvcUrl = string.IsNullOrEmpty(node.UnresolvedUrl) && this.UsesDefaultUrlResolver(node); + bool isMvcUrl = string.IsNullOrEmpty(node.UnresolvedUrl) && node.UsesDefaultUrlResolver(); // Only store URLs if they are clickable and are configured using the Url // property or provided by a custom URL resolver. @@ -816,12 +816,6 @@ protected virtual ISiteMapNode ReturnNodeIfAccessible(ISiteMapNode node) return null; } - protected virtual bool UsesDefaultUrlResolver(ISiteMapNode node) - { - return string.IsNullOrEmpty(node.UrlResolver) || - typeof(MvcSiteMapProvider.Web.UrlResolver.SiteMapNodeUrlResolver).Equals(Type.GetType(node.UrlResolver, false)); - } - protected virtual void AssertSiteMapNodeConfigurationIsValid(ISiteMapNode node) { ThrowIfTitleNotSet(node);