MVCSiteMapProvider ignore parameters - asp.net

I am using MVCSiteMapProvider.MVC5 and I am trying to set up my site map.
My routes are:
notifications/
notifications/Alarm/
notifications/Warning/
notifications/Information/
The Alarm, Warning and Information are passed to the "notificationFilter" action parameter.
This is my basic site map which currently shows by breadcrumb for route notifications/ as Home>Notifications.
<mvcSiteMapNode title="Home" controller="Dashboard" action="System">
<mvcSiteMapNode title="Vacuum Management" controller="Dashboard" action="SubSystem" />
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" />
</mvcSiteMapNode>
What I would like to do is add a catch all so that if the "notificationFilter" parameter is passed (e.g. notifications/Alarm/) it still displays the breadcrumb as Home>Notifications and ignores the parameter.
I have tried this:
<mvcSiteMapNode title="Home" controller="Dashboard" action="System">
<mvcSiteMapNode title="Vacuum Management" controller="Dashboard" action="SubSystem" />
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" notificationFilter="Alarm" />
Which works for notifications/Alarm but then nothing else. I also tried adding multiple lines:
<mvcSiteMapNode title="Home" controller="Dashboard" action="System">
<mvcSiteMapNode title="Vacuum Management" controller="Dashboard" action="SubSystem" />
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" notificationFilter="Alarm" />
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" notificationFilter="Warning" />
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" notificationFilter="Information" />
But because the title is the key the the bread crumb would display different text.
All help appreciated.
Thanks in advance!
Route Config:
routes.MapRoute(
name: "NotificationsSystem",
url: "notifications",
defaults: new { controller = "Notifications", action = "SystemNotifications", notificationFilter = "" }
);
routes.MapRoute(
name: "NotificationsSystemFiltered",
url: "notifications/{notificationFilter}",
defaults: new { controller = "Notifications", action = "SystemNotifications", notificationFilter = "" }
);

As per the documentation, getting a single node to match any value for a particular parameter can be done by using preservedRouteParameters.
<mvcSiteMapNode title="Notifications" controller="Notifications" action="SystemNotifications" preservedRouteParameters="notificationFilter" />
This works well when your node has no children, but if you put this attribute on nodes that do have children you need to take into consideration what will happen when the user navigates back up the hierarchy.

Related

asp.net web pages. Default route

How I can set up my site (asp.net web pages) to get urldata for default page?
site.com/default/1
this work,
but site.com/1 return 404 error.
In web forms this work fine, but in web pages no
In Solution Explorer, there is a file called as App_Start. You can configure RouteConfig.cs file whatever you want. There is the example of Route function :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
If you have a default.cshtml that is always the default start page, even if it´s not listed in the list with default pages under Settings. I guess it´s because how the routing works in ASP.NET Web Pages.
If you want a index.html as start page, you need to add it to the list with default pages, and remove the default.cshtml if you have that.
see This link
<defaultDocument enabled="true">
<files>
<add value="Default.htm" />
<add value="Default.asp" />
<add value="index.htm" />
<add value="index.html" />
<add value="iisstart.htm" />
<add value="default.aspx" />
</files>
</defaultDocument>
Here Similar Post

XmlSiteMapProvider only parse the first node

I have an annoying problem and i can't find any start of a solution, so i hope you can help me.
I have a sitemap with roles defined for each node :
<?xml version="1.0" encoding="utf-8"?>
<siteMap enableLocalization="true">
<siteMapNode title="" url="" roles="">
<siteMapNode title="default" url="~/Default.aspx" roles="user" />
<siteMapNode title="supervision" url="~/EcranSupervision.aspx" roles="Admin" />
<siteMapNode title="exploitation" url="~/ChaineTraitementList.aspx" roles="Admin" />
</siteMapNode>
</siteMap>
And in my web.config, i enable security and i use a custom provider :
<siteMap defaultProvider="MainMenuSitemap">
<providers>
<add name="MainMenuSitemap" type="UbiXmlSiteMapProvider" siteMapFile="Web.sitemap" securityTrimmingEnabled="true" />
</providers>
</siteMap>
In my provider, i only override IsAccessibleToUser to do my logic :
public class UbiXmlSiteMapProvider : XmlSiteMapProvider
{
public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
{
// custom logic here
}
}
My problem is that the node used in IsAccessibleToUser is always the one with the url "Default.aspx".
So if I have the role to see it, all the nodes are shown and if i don't have the role, none of the nodes are shown.
I don't understand what is wrong here.
Do you have a hint for me ?

MVC Sitemap show only parent nodes

I want show only my parent nodes in my View.
This is my sitemap:
<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0" enableLocalization="true">
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="About" controller="Home" action="About"/>
<mvcSiteMapNode title="Contact" controller="Home" action="Contact"/>
</mvcSiteMapNode>
<mvcSiteMapNode title="Test" controller="Test" action="Index">
<mvcSiteMapNode title="Teste2" controller="Test" action="Index"/>
<mvcSiteMapNode title="Teste3" controller="Test" action="Index"/>
</mvcSiteMapNode>
</mvcSiteMap>
How can I use the html helper #Html.MvcSiteMap().Menu() to show only the parent nodes, and only the child nodes?
Like this:
Parents:
Home
Test
Childs
About
Contacts
Teste2
Teste3
Thanks.
Try for top level
#Html.MvcSiteMap().Menu(0, true, false, 1)
Second level
#Html.MvcSiteMap().Menu(2, 1, true)
This tutorial may help

How do I create multiple different layouts using only one SiteMap?

Suppose I have 3 areas on my page that have links
Header
Menu
Footer
Each have different links, but some links overlap:
I am using MVCSiteMapProvider to accomplish this. I have a SiteMap:
<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0"
xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0 MvcSiteMapSchema.xsd"
enableLocalization="false">
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="Link 1" controller="" action="" visibility="Header, Footer" />
<mvcSiteMapNode title="Link 2" controller="" action="" visibility="Menu" />
<mvcSiteMapNode title="Link 3" controller="" action="" visibility="Header, Menu" />
<mvcSiteMapNode title="Link 4" controller="" action="" visibility="Menu, Footer, Header" />
</mvcSiteMapNode>
</mvcSiteMap>
I thought that maybe Visibility was the way to do this, but it doesn't work the way I want it.
Public Class MenuVisibilityProvider
Implements ISiteMapNodeVisibilityProvider
Public Function IsVisible(ByVal node As SiteMapNode, ByVal context As HttpContext, ByVal sourceMetadata As IDictionary(Of String, Object)) As Boolean Implements ISiteMapNodeVisibilityProvider.IsVisible
Dim visibility As String = node("visibility")
If visibility IsNot Nothing Then Return True
Select Case visibility
Case "Menu"
Case "Header"
Case "Footer"
Return True
End Select
Return False
End Function
End Class
I end up with all of the links in every area.
Edit for clarification:
This is a similar question, but also with no answer:
https://stackoverflow.com/questions/12845929/how-to-show-partial-site-map-including-current-node-with-mvcsitemapprovider
Also similar, but I don't want to have to make multiple SiteMaps: Using Multiple MvcSiteMaps
OP here. I accomplished this using only one site map.
To do this:
I added visibility tags to each sitemap element, for example:
<mvcSiteMapNode title="Login" controller="Members" action="Login" visibility="SideMenu Footer" />
In this example "SideMenu Footer" are my tags. I will use String.Contains() later to determine visibility.
I added multiple different siteMap providers in the Web.config with different siteMapNodeVisibilityProvider:
<siteMap defaultProvider="MvcSiteMapProvider" enabled="true">
<providers>
<clear />
<add name="MvcSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" />
<add name="NavSiteMapProvider" ... siteMapNodeVisibilityProvider="RootNamespace.Namespace.NavVisibilityProvider, RootNamespace" ... />
<add name="FooterSiteMapProvider" ... siteMapNodeVisibilityProvider="RootNamespace.Namespace.FooterVisibilityProvider, RootNamespace" ... />
</providers>
</siteMap>
I created a new code file (class) called CustomVisibilityProvider. Inside I created a class for each provider (Footer, Nav, Menu etc)
' Note: VB.NET :P
Public Class MenuVisibilityProvider
Implements ISiteMapNodeVisibilityProvider
Public Function IsVisible(ByVal node As SiteMapNode, ByVal context As HttpContext, ByVal sourceMetadata As IDictionary(Of String, Object)) As Boolean Implements ISiteMapNodeVisibilityProvider.IsVisible
Dim visibility As String = node("visibility")
If visibility Is Nothing Then Return False
If visibility.Contains("Menu") Then Return True
Return False
End Function
End Class
Public Class NavVisibilityProvider
Implements ISiteMapNodeVisibilityProvider
...
If visibility.Contains("Nav") Then Return True
...
End Class
When you're in a view file:
#Html.MvcSiteMap("FooterSiteMapProvider").Menu
Note: You can give the Menu() a custom view also, so that nav, footer, menu etc render the links differently (some might be in <ul></ul> format while others might be <a> tags).

roles based menu does not work, what am I doing wrong?

I can't figure this one out.
I have the following SiteMap
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="~/" title="Root" description="Go root">
<siteMapNode url="~/h" title="Home" description="Go home" />
<siteMapNode url="~/h/uo" title="Ultima Online" description="Ultima Online">
<siteMapNode url="~/h/uo/get" roles="RegisteredUser" title="Get account!" description="Get account!" />
</siteMapNode>
</siteMapNode>
</siteMap>
I've an XmlSiteMapProvider with securityTrimmingEnabled="true", which points to this site map file.
The file I want to trim has an authorization rule in it's folder's web.config
<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>
The file can't be accessed via url, if I type http://localhost/h/uo/get I get redirected to login page.
I've set up an <asp:Menu> like this in the Master page file:
<asp:SiteMapDataSource ID="MenuSiteMap" ShowStartingNode="false"
SiteMapProvider="MenuSiteMapProvider" runat="server"
/>
<div>
<asp:Menu ID="NavigationMenu" runat="server" DataSourceID="MenuSiteMap"
CssClass="menu" EnableViewState="false"
IncludeStyleBlock="false" Orientation="Horizontal"
/>
</div>
Yet, when the page is rendered, I see the Get account node that is supposed to be trimmed when I'm not even logged in, no matter what.
What am I doing wrong?
Is there any other way to build a security trimming enabled site map navigation menu?
I'm using ASP.NET 4.0, and URL-rewritting with an HttpModule.
In reading http://forums.asp.net/t/975077.aspx/1 I found out that this is exactly what is happening to me.
If the node doesn't have an URL it behaves fine, but if it does, like all of my nodes do. Security trimming is just ignored.
I resolved my problem by resorting to a more intuitive role based site map implementation, to say:
public class TrimmingXmlSiteMapProvider : XmlSiteMapProvider
{
public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
{
if (node.Roles.Cast<string>().Any(r => r == "*"))
return true;
if (node.Roles.Count > 0 && node.Roles.Cast<string>().Count(Roles.IsUserInRole) == 0)
return false;
return node.ParentNode != null && node.ParentNode.IsAccessibleToUser(context);
}
}
Then, the only change I had to make was add an asterisk to the root level's role definition.
How does this work?
First I check if any of the roles definied for this node is an asterisk, if that's the case, then I can see the node.
Second, if the node isn't everyone-level, I check if there are any roles specified, and if the logged in user is part of at least one of them.
Lastly, I check if there is a parent node, and just inherit their rule.
This allows the security trimming to actually be "SECURITY TRIMMING" and not well, however the heck it's supposed to be working by default.

Resources