-
Notifications
You must be signed in to change notification settings - Fork 1
Advanced Node Visibility with ISiteMapNodeVisibilityProvider
In some situations, nodes should be visible in the breadcrumb trail but not in a complete sitemap. This can be solved using the concept of ISiteMapNodeVisibilityProvider, that can be specified globally for every node in the sitemap or granularly on a specific sitemap node.
It is possible to implement your own ISiteMapNodeVisibilityProvider, as is done in the sample application. There is also a standard FilteredSiteMapNodeVisibilityProvider, which filters sitemap node visibility based on the control that is currently rendering the sitemap node.
You can control the setting of whether the visibility of the parent node will be inherited by its children using the VisibilityAffectsDescendants setting. This setting can be applied SiteMap wide or specified explicitly on by calling one of the overloads that accept the visibilityAffectsDescendants parameter on the Menu or SiteMap HTML helpers. Although it is not the default setting, we recommend setting this value to false for the most flexibility with visibility providers, which will allow you to make visible children of invisible parent nodes.
For internal DI you can set the property SiteMap wide using the following setting in web.config:
<appSettings>
<add key="MvcSiteMapProvider_VisibilityAffectsDescendants" value="false"/>
</appSettings>
For external DI, you can just set the variable on at the top of the module file, which is passed into the constructor of the SiteMapBuilderSet class.
bool visibilityAffectsDescendants = false;
In order to make use of FilteredSiteMapNodeVisibilityProvider, the following steps should be taken:
1 - If the FilteredSiteMapNodeVisibilityProvider should be used globally for all nodes in the sitemap, modify Web.config and set the appSettings MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider attribute to "MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider". Here's an example when using the internal DI container:
<appSettings>
<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"/>
</appSettings>
If using an external DI container, you need to set the defaultProviderName
constructor argument of SiteMapNodeVisibilityProviderStrategy in your MvcSiteMapProvider module (the name of the module varies depending on the DI container). This is how that would look with Ninject:
this.Kernel.Bind<ISiteMapNodeVisibilityProviderStrategy>().To<SiteMapNodeVisibilityProviderStrategy>()
.WithConstructorArgument("defaultProviderName", "MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider");
2 - For every node, specify the visibility attribute. Here's an example in XML:
<mvcSiteMapNode title="Administration" area="Admin" clickable="false" visibility="SiteMapPathHelper,!*" />
And here is the same example using SiteMapNodeAttribute.
[MvcSiteMapNode(Title = "Administration", Clickable = false, Attributes = @"{ ""visibility"": ""SiteMapPathHelper,!*"" }")]
Note: Due to data type restrictions of .NET attributes, the Attributes must be declared as a JSON string.
The visibility attribute can contain a comma-separated list of controls in which the sitemap node should be rendered or not. These are processed left-to-right and can be inverted using an exclamation mark. Here's a break down of the above example:
Directive | Meaning |
---|---|
SiteMapPathHelper | The node is visible in the SiteMapPathHelper. |
!* | The node is invisible in any other control. |
Note that an implicit * (The node is visible in any control) is added at the end of the list.
Here is a list of the types that can be specified in the FilteredSiteMapNodeVisibilityProvider.
Type | What it Affects |
---|---|
CanonicalHelper | The Canonical HTML Helper |
MenuHelper | The Menu HTML Helper |
MetaRobotsHelper | The Meta Robots HTML Helper |
SiteMapHelper | The SiteMap HTML Helper |
SiteMapPathHelper | The SiteMapPath HTML Helper |
SiteMapTitleHelper | The Title HTML Helper |
XmlSiteMapResult | The sitemaps XML output of the /sitemap.xml endpoint |
As of v4.4.8 you can use the FilteredSiteMapNodeVisibilityProvider to specify named instances of the Menu and other HTML helpers instead of specifying the type of control. This is helpful if for example you wanted to have a main menu and a footer menu.
To name an HTML helper, call one of the overrides that has a sourceMetadata argument and pass the name.
@Html.MvcSiteMap().Menu(new { name = "MainMenu" })
@Html.MvcSiteMap().Menu(new { name = "FooterMenu" })
You can then use the name instead of the type name to specify visible or not visible, as in the previous example.
<mvcSiteMapNode title="Home" controller="Home" action="Index" visibility="MenuHelper,!*" />
<mvcSiteMapNode title="Contact" controller="Home" action="Contact" visibility="MainMenu,!*" />
<mvcSiteMapNode title="About" controller="Home" action="About" visibility="FooterMenu,!*" />
This example will make the home page visible on all menus (but invisible everywhere else), make the contact page visible only on the main menu, and make the about page visible only on the footer menu.
You can add the suffix IfSelected
to either the HTML helper type name or the named instance name to make the node only visible if it is in the current path (that is, between the current node and the root node, inclusive).
<mvcSiteMapNode title="Contact" controller="Home" action="Contact" visibility="MainMenuIfSelected,!*" />
You can also specify this behavior for all HTML helpers and the /sitemap.xml endpoint at once using IfSelected
.
<mvcSiteMapNode title="Contact" controller="Home" action="Contact" visibility="IfSelected,!*" />
In order to create a custom SiteMapNodeVisibilityProvider, to following steps should be taken:
1 - Create a new class implementing SiteMapNodeVisibilityProviderBase
using System.Collections.Generic;
using System.Web;
using MvcSiteMapProvider;
namespace MyCompany
{
public class MyCustomVisibilityProvider : SiteMapNodeVisibilityProviderBase
{
public bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
// Is a visibility attribute specified?
string visibility = node.Attributes["visibility"];
if (string.IsNullOrEmpty(visibility))
{
return true;
}
visibility = visibility.Trim();
//process visibility
switch (visibility)
{
case "Condition1":
//...
return false;
case "Condition2":
//...
return false;
}
return true;
}
}
}
2 - Modify Web.config and set the MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider (internal DI container only) to contain your Visibility Provider namespace and assembly like so:
<appSettings>
<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MyCompany.MyCustomVisibilityProvider, MyWebProject"/>
</appSettings>
MyWebProject should be the name of the dll that is created by your MVC project
3 - For every node, specify the visibility attribute. Here's an example in XML:
<mvcSiteMapNode title="Administration" area="Admin" visibility="Condition1" />
<mvcSiteMapNode title="Settings" area="Admin" visibility="Condition2" />
Note that if you need to, you can pass custom information from the HTML helper declaration to your visibility provider by using the sourceMetadata parameter of the HTML helper (or the /sitemaps.xml endpoint) as shown in the section Named HTML Helper Instances above.
@Html.MvcSiteMap().SiteMapPath(new { someKey = "Some Value" })
It will then be available through the sourceMetadata parameter of the IsVisible method of your custom visibility provider.
public class MyCustomVisibilityProvider : SiteMapNodeVisibilityProviderBase
{
public bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
// Retrieve the value named someKey
var value = sourceMetadata["someKey"];
// Value of value variable will be "Some Value"
}
}
It is possible to override the default visibility provider with another one by specifying the visibility provider directly on the mvcSiteMapNode element. This means that each node can have a separate visibility provider if you have different complex logic that needs to be specified for a node or group of nodes.
<mvcSiteMapNode title="Settings" area="Admin" visibility="Condition2" visibilityProvider="Namespace.MyCustomVisibilityProvider2, AssemblyName" />
- [Wiki Home] (.)
- [Release Notes] (https://github.com/maartenba/MvcSiteMapProvider/releases)
Want to contribute? See our [Contributing to MvcSiteMapProvider] (https://github.com/maartenba/MvcSiteMapProvider/blob/master/CONTRIBUTING.md) guide.
- [Upgrading from v3 to v4] (Upgrading-from-v3-to-v4)
- [Routing Basics] (Routing-Basics)
- Configuring MvcSiteMapProvider
- Defining Sitemap Nodes in XML
- Defining Sitemap Nodes using .NET Attributes
- Defining Sitemap Nodes using IDynamicNodeProvider
- HtmlHelper Extensions
- Controlling URL Behavior
- Using Action Filter Attributes
- Sitemaps XML Protocol Endpoint for Search Engines
- Using Custom Attributes on a Node
- Specifying Node Order
- Advanced Node Visibility
- Multiple Navigation Paths to a Single Page
- [Multiple Sitemaps in One Application] (Multiple-Sitemaps-in-One-Application)
- [Security Trimming] (Security-Trimming)
[Version 3.x Documentation] (Version-3.x-Documentation)
Other places around the web have some documentation that is helpful for getting started and finding answers that are not found here.
- [MvcSiteMapProvider 4.0 - A Test Drive] (http://www.shiningtreasures.com/post/2013/08/07/MvcSiteMapProvider-40-a-test-drive)
- [MvcSiteMapProvider 4.0 - SEO Features Tutorial] (http://www.shiningtreasures.com/post/2013/08/10/mvcsitemapprovider-4-seo-features)
- [How to Make MvcSiteMapProvider Remember a User’s Position] (http://www.shiningtreasures.com/post/2013/09/02/how-to-make-mvcsitemapprovider-remember-a-user-position)
- [MvcSiteMapProvider 4.0 - Cache Configuration] (http://www.shiningtreasures.com/post/2013/08/11/mvcsitemapprovider-4-cache-configuration)
- [MvcSiteMapProvider 4.0 - Extending the Cache] (http://www.shiningtreasures.com/post/2013/08/13/mvcsitemapprovider-4-extending-the-cache)
- [MvcSiteMapProvider 4.0 - Unit Testing with the SiteMaps Static Methods] (http://www.shiningtreasures.com/post/2013/08/14/mvcsitemapprovider-4-unit-testing-with-the-sitemaps-static-methods)
- [Debugging an MvcSiteMapProvider Configuration] (http://www.shiningtreasures.com/post/2013/08/21/debugging-an-mvcsitemapprovider-configuration)
- [Converting from C# to Vb MvcSiteMapProvider] (http://www.developerfusion.com/thread/112710/converting-from-c-to-vb-mvcsitemapprovider/)
- [NightOwl888's MvcSiteMapProvider Demos] (https://github.com/NightOwl888?tab=repositories) - Filter for "MvcSiteMapProvider" to see the most relevant.
- [MvcSiteMapProvider Tutorial and Examples] (http://edspencer.me.uk/2011/02/10/mvc-sitemap-provider-tutorial/)
- [MvcSiteMapProvider Tutorial 2 - Breadcrumbs] (http://edspencer.me.uk/2011/09/20/mvc-sitemap-provider-tutorial-2-breadcrumbs/)
- [Getting Started with MvcSiteMapProvider] (http://blog.danstuken.com/2011/04/29/getting-started-with-mvcsitemapprovider/)
- [Inside the MvcSiteMapProvider - Part 1] (http://xharze.blogspot.com/2012/04/inside-mvcsitemapprovider-part-1.html)
- [Inside the MvcSiteMapProvider - Part 2: Dynamic node providers] (http://xharze.blogspot.com/2012/04/inside-mvcsitemapprovider-part-2.html)
- [Inside the MvcSiteMapProvider - Part 3: The ISiteMapVisibilityProvider] (http://xharze.blogspot.com/2012/04/inside-mvcsitemapprovider-part-3.html)
- [Inside the MvcSiteMapProvider - Part 4: The IAclModule] (http://xharze.blogspot.com/2012/04/inside-mvcsitemapprovider-part-4.html)
- [Inside the MvcSiteMapProvider - Part 5: The ISiteMapNodeUrlResolver] (http://xharze.blogspot.com/2012/04/inside-mvcsitemapprovider-part-5.html)
- [Styling MvcSiteMapProvider with CSS] (http://tutsblog.net/styling-mvc-sitemap-provider-with-css/)
- [Using MvcSiteMapProvider with Twitter Bootstrap] (http://codingit.wordpress.com/2013/05/03/using-mvcsitemapprovider-with-twitter-bootstrap/)
- [ASP.NET MVC Menu using Site Map Provider & Bootstrap Navbar] (http://joeylicc.wordpress.com/2013/06/04/asp-net-mvc-menu-using-site-map-provider-bootstrap-navbar/)
- [StackOverflow MvcSiteMapProvider] (http://stackoverflow.com/questions/tagged/mvcsitemapprovider)
- [StackOverflow MvcSiteMap] (http://stackoverflow.com/questions/tagged/mvcsitemap)
- [StackOverflow ASP.NET MVC SiteMap] (http://stackoverflow.com/questions/tagged/asp.net-mvc-sitemap)
- [CodePlex Discussion Forum (no longer maintained)] (http://mvcsitemap.codeplex.com/discussions/topics/general?size=2147483647)
- [Telerik Forum] (http://www.telerik.com/search.aspx?insection=False&start=0&client=telerik_developer_tools&q=MvcSiteMapProvider&sid=1)
- [maartenba's blog] (http://blog.maartenballiauw.be/search.aspx?q=mvcsitemapprovider)
- [NightOwl888's blog] (http://www.shiningtreasures.com/category/MvcSiteMapProvider)