Skip to content

Commit

Permalink
Fixes #291
Browse files Browse the repository at this point in the history
- Throw exception in the case where a specified dynamic node provider doesn't match.
- Convert .NET type string for dynamic node providers, visibility providers, and URL resolvers to .NET type before making comparison so that any valid variants of a .NET type string (including fully-qualified names, for strong naming) can be used.
- Reworked the logic of dynamic node, visibility provider, and URL resolver strategy classes so the AppliesTo() method is always called including the case where the providerName is empty string. This allows that case to be taken into account for custom providers.
  • Loading branch information
NightOwl888 committed Mar 1, 2014
1 parent 354699e commit 9582068
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ public abstract class DynamicNodeProviderBase
/// <summary>
/// Determines whether the provider instance matches the name
/// </summary>
/// <param name="providerName">The name of the dynamic node provider. This can be any string, but for backward compatibility the type name can be used.</param>
/// <param name="providerName">The name of the dynamic node provider. This can be any string, but for backward compatibility the type name is used.</param>
/// <returns>
/// True if the provider name matches.
/// </returns>
public virtual bool AppliesTo(string providerName)
{
return this.GetType().ShortAssemblyQualifiedName().Equals(providerName, StringComparison.InvariantCulture);
if (string.IsNullOrEmpty(providerName))
return false;

return this.GetType().Equals(Type.GetType(providerName, false));
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MvcSiteMapProvider
{
/// <summary>
/// Tracks all of the registered instances of <see cref="T:MvcSiteMapProvider.IDynamicNodeProvider"/> and
/// allows the caller to get a specific named instance of this interface at runtime.
/// allows the caller to get a specific named instance of <see cref="T:MvcSiteMapProvider.IDynamicNodeProvider"/> at runtime.
/// </summary>
public class DynamicNodeProviderStrategy
: IDynamicNodeProviderStrategy
Expand All @@ -25,13 +25,19 @@ public DynamicNodeProviderStrategy(IDynamicNodeProvider[] dynamicNodeProviders)

public IDynamicNodeProvider GetProvider(string providerName)
{
return dynamicNodeProviders.FirstOrDefault(x => x.AppliesTo(providerName));
var provider = this.dynamicNodeProviders.FirstOrDefault(x => x.AppliesTo(providerName));
if (provider == null && !string.IsNullOrEmpty(providerName))
{
throw new MvcSiteMapException(string.Format(Resources.Messages.NamedDynamicNodeProviderNotFound, providerName));
}

return provider;
}

public IEnumerable<DynamicNode> GetDynamicNodeCollection(string providerName, ISiteMapNode node)
{
var provider = GetProvider(providerName);
if (provider == null) return new List<DynamicNode>();
var provider = this.GetProvider(providerName);
if (provider == null) return new List<DynamicNode>(); // No provider, return empty collection
return provider.GetDynamicNodeCollection(node);
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,7 @@ Valid keys may be "area", "controller", "action", and custom parameters that are

You may suppress this error message by calling an overload of the RouteValues.Add() or RouteValues.AddRange() that accepts the 'throwIfReservedKey' argument and passing false for the value. Note that if you do this, attempting to add a key with a reserved name to the RouteValues dictionary will silently fail.</value>
</data>
<data name="NamedDynamicNodeProviderNotFound" xml:space="preserve">
<value>The dynamic node provider instance named '{0}' was not found. Check your DI configuration to ensure a dynamic node provider instance with this name exists and is configured correctly.</value>
</data>
</root>
4 changes: 2 additions & 2 deletions src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,8 @@ protected virtual ISiteMapNode ReturnNodeIfAccessible(ISiteMapNode node)

protected virtual bool UsesDefaultUrlResolver(ISiteMapNode node)
{
return string.IsNullOrEmpty(node.UrlResolver) ||
node.UrlResolver.Equals(typeof(MvcSiteMapProvider.Web.UrlResolver.SiteMapNodeUrlResolver).ShortAssemblyQualifiedName(), StringComparison.InvariantCulture);
return string.IsNullOrEmpty(node.UrlResolver) ||
typeof(MvcSiteMapProvider.Web.UrlResolver.SiteMapNodeUrlResolver).Equals(Type.GetType(node.UrlResolver, false));
}

protected virtual void AssertSiteMapNodeConfigurationIsValid(ISiteMapNode node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public abstract class SiteMapNodeVisibilityProviderBase
/// Determines whether the node is visible. Override this member to provide alternate implementations of VisibilityProvider.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="sourceMetadata">The source metadata.</param>
/// <param name="sourceMetadata">The source meta-data.</param>
/// <returns>
/// <c>true</c> if the specified node is visible; otherwise, <c>false</c>.
/// </returns>
Expand All @@ -25,13 +25,16 @@ public abstract class SiteMapNodeVisibilityProviderBase
/// <summary>
/// Determines whether the provider instance matches the name
/// </summary>
/// <param name="providerName">The name of the visibiltiy provider. This can be any string, but for backward compatibility the type name can be used.</param>
/// <param name="providerName">The name of the visibility provider. This can be any string, but for backward compatibility the type name is used.</param>
/// <returns>
/// <c>true</c> if the provider name matches; otherwise <c>false</c>.
/// </returns>
public virtual bool AppliesTo(string providerName)
{
return this.GetType().ShortAssemblyQualifiedName().Equals(providerName, StringComparison.InvariantCulture);
if (string.IsNullOrEmpty(providerName))
return false;

return this.GetType().Equals(Type.GetType(providerName, false));
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MvcSiteMapProvider
{
/// <summary>
/// Tracks all of the registered instances of <see cref="T:MvcSiteMapProvider.ISiteMapNodeVisiblityProvider"/> and
/// allows the caller to get a specific named instance of this interface at runtime.
/// allows the caller to get a specific named instance of <see cref="T:MvcSiteMapProvider.ISiteMapNodeVisiblityProvider"/> at runtime.
/// </summary>
public class SiteMapNodeVisibilityProviderStrategy
: ISiteMapNodeVisibilityProviderStrategy
Expand All @@ -28,27 +28,25 @@ public SiteMapNodeVisibilityProviderStrategy(ISiteMapNodeVisibilityProvider[] si

public ISiteMapNodeVisibilityProvider GetProvider(string providerName)
{
ISiteMapNodeVisibilityProvider provider = null;
if (!String.IsNullOrEmpty(providerName))
if (string.IsNullOrEmpty(providerName))
{
provider = siteMapNodeVisibilityProviders.FirstOrDefault(x => x.AppliesTo(providerName));
if (provider == null)
{
throw new MvcSiteMapException(String.Format(Resources.Messages.NamedSiteMapNodeVisibilityProviderNotFound, providerName));
}
// Get the configured default provider
providerName = this.defaultProviderName;
}
else if (!string.IsNullOrEmpty(defaultProviderName))

var provider = this.siteMapNodeVisibilityProviders.FirstOrDefault(x => x.AppliesTo(providerName));
if (provider == null && !string.IsNullOrEmpty(providerName))
{
// Return the configured default provider
provider = siteMapNodeVisibilityProviders.FirstOrDefault(x => x.AppliesTo(defaultProviderName));
throw new MvcSiteMapException(string.Format(Resources.Messages.NamedSiteMapNodeVisibilityProviderNotFound, providerName));
}

return provider;
}

public bool IsVisible(string providerName, ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
var provider = GetProvider(providerName);
if (provider == null) return true; // If no default provider configured, then always visible.
var provider = this.GetProvider(providerName);
if (provider == null) return true; // If no provider configured, then always visible.
return provider.IsVisible(node, sourceMetadata);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ public abstract class SiteMapNodeUrlResolverBase
/// <summary>
/// Determines whether the provider instance matches the name
/// </summary>
/// <param name="providerName">The name of the URL resolver. This can be any string, but for backward compatibility the type name can be used.</param>
/// <param name="providerName">The name of the URL resolver. This can be any string, but for backward compatibility the type name is used.</param>
/// <returns>
/// <c>true</c> if the provider name matches; otherwise <c>false</c>.
/// </returns>
public virtual bool AppliesTo(string providerName)
{
return this.GetType().ShortAssemblyQualifiedName().Equals(providerName, StringComparison.InvariantCulture);
if (string.IsNullOrEmpty(providerName))
return false;

return this.GetType().Equals(Type.GetType(providerName, false));
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
namespace MvcSiteMapProvider.Web.UrlResolver
{
/// <summary>
/// Tracks all of the registered instances of <see cref="T:MvcSiteMapProvider.ISiteMapNodeUrlResolver"/> and
/// allows the caller to get a specific named instance of this interface at runtime.
/// Tracks all of the registered instances of <see cref="T:MvcSiteMapProvider.Web.UrlResolver.ISiteMapNodeUrlResolver"/> and
/// allows the caller to get a specific named instance of <see cref="T:MvcSiteMapProvider.Web.UrlResolver.ISiteMapNodeUrlResolver"/> at runtime.
/// </summary>
public class SiteMapNodeUrlResolverStrategy
: ISiteMapNodeUrlResolverStrategy
Expand All @@ -26,22 +26,22 @@ public SiteMapNodeUrlResolverStrategy(ISiteMapNodeUrlResolver[] siteMapUrlResolv

public ISiteMapNodeUrlResolver GetProvider(string providerName)
{
var provider = siteMapUrlResolvers.FirstOrDefault(x => x.AppliesTo(providerName));
var provider = this.siteMapUrlResolvers.FirstOrDefault(x => x.AppliesTo(providerName));
if (provider == null)
{
if (!String.IsNullOrEmpty(providerName) && !providerName.Equals("default", StringComparison.InvariantCultureIgnoreCase))
if (!string.IsNullOrEmpty(providerName))
{
throw new MvcSiteMapException(String.Format(Resources.Messages.NamedUrlResolverNotFound, providerName));
throw new MvcSiteMapException(string.Format(Resources.Messages.NamedUrlResolverNotFound, providerName));
}
// Return the SiteMapNodeUrlResolver type by default if the requested type is empty string or "default".
provider = siteMapUrlResolvers.FirstOrDefault(x => x.GetType().Equals(typeof(SiteMapNodeUrlResolver)));
// Return the SiteMapNodeUrlResolver type by default if the requested type is empty string.
provider = this.siteMapUrlResolvers.FirstOrDefault(x => x.GetType().Equals(typeof(SiteMapNodeUrlResolver)));
}
return provider;
}

public string ResolveUrl(string providerName, ISiteMapNode node, string area, string controller, string action, IDictionary<string, object> routeValues)
{
var provider = GetProvider(providerName);
var provider = this.GetProvider(providerName);
if (provider == null) return string.Empty;
return provider.ResolveUrl(node, area, controller, action, routeValues);
}
Expand Down

0 comments on commit 9582068

Please sign in to comment.