Mixing MVC and URL nodes in the SiteMap

Oct 8, 2010 at 8:08 PM

We have a hybrid site using a mix of WebForms and MVC. We would like to show both nodes in the site map.  From other threads it looks like it is/was possible http://mvcsitemap.codeplex.com/Thread/View.aspx?ThreadId=67766.

I've tried this, but it never seems to like the nodes that aren't mvcSiteNode. In fact, the root node has to be the following:

<mvcSiteMap xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-2.0" enableLocalization="true">

Anything else and it won't find the root node. From the examples in the other thread, and from previous version on the product home page, something like the following should work, but doesn't.

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <mvcSiteMapNode title="Home" controller="Foo" action="Index" >
    <siteMapNode url="~/bar.aspx" title="Bar" />
    <mvcSiteMapNode title="Baz" controller="Foo" action="Baz" />    
  </mvcSiteMapNode>
</siteMap>

I'm trying to do that something similar to that. Is this still possible?

Coordinator
Oct 11, 2010 at 7:36 AM

This was supported in the previous version but has not been ported into 2.0+

You can try this one but it is still unsupported. If you really require this to work, please let me know.

<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap>
  <mvcSiteMapNode title="Home" controller="Foo" action="Index" >
    <mvcSiteMapNode url="~/bar.aspx" title="Bar" />
    <mvcSiteMapNode title="Baz" controller="Foo" action="Baz" />   
  </mvcSiteMapNode>
</mvcSiteMap>

Oct 11, 2010 at 4:06 PM

Thanks. It actually works if you leave off the "~". 

<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap>
  <mvcSiteMapNode title="Home" controller="Foo" action="Index" >
    <mvcSiteMapNode url="/bar.aspx" title="Bar" />
    <mvcSiteMapNode title="Baz" controller="Foo" action="Baz" />    
  </mvcSiteMapNode>
</mvcSiteMap>

Dec 7, 2010 at 7:38 PM

Greetings. I've got the same problem, I've tried starting from scratch, modifying this code, and everything in between. Mixing URLs and MVC is a requirement for my project. Is there some way to use a node-specific provider to resolve the legacy URLs? 

Coordinator
Dec 8, 2010 at 6:27 AM
markborcherding wrote:

Thanks. It actually works if you leave off the "~". 

<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap>
  <mvcSiteMapNode title="Home" controller="Foo" action="Index" >
    <mvcSiteMapNode url="/bar.aspx" title="Bar" />
    <mvcSiteMapNode title="Baz" controller="Foo" action="Baz" />    
  </mvcSiteMapNode>
</mvcSiteMap>

 

Dec 8, 2010 at 4:35 PM
Edited Dec 10, 2010 at 4:14 PM

Unfortunately, I'm getting some errors with this approach (using V 2.2.1). If I don't use security trimming, everything is OK. But, security trimming is the hangup. The system chokes when checking permission on a url node, because of course there is no controller or action.

One solution would be to have to use a custom aclModule that interrogates the roles attribute. I might try that.

Another solution would be to allow the old siteMapNode element. And, for those elements, interrogate the roles attribute if required. That doesn't look to hard. But, the project has grown so complex that I don't know what effects that would have downstream. Maybe I'll just try it.

--edit to fix formatting

Dec 8, 2010 at 5:38 PM
Edited Dec 10, 2010 at 4:15 PM

Problem solved. I'm going to explain my own solution, for the benefit of others.

By default, the system uses the DefaultAclModule. This module uses two "child" modules. It checks the Roles attribute, and any authorization attributes on the controllers. Since these url nodes don't have controllers or actions, that authorization-attribute-checking fails.

Fortunately, the system is built to handle this. One can specify any AclModule. So, in my web.config, I just said aclModule="MvcSiteMapProvider.XmlRolesAclModule, MvcSiteMapProvider".

This avoids checking the authorization attributes (which could be problematic for some, though could improve speed???). The permissions are only checked against the Roles attributes. That's OK with me, though now I have to maintain three sets of permissions. (Attributes for MVC, Roles for legacy pages, and web.config for legacy pages).

--edit to fix formatting

Dec 8, 2010 at 9:08 PM

Sorry to keep coming back to this one. But, there's also a problem with the DefaultNodeKeyGenerator. For url nodes, the "area" is an empty string, rather than null, so the URL is not appended to the key. This results in duplicate keys, and pages are not appearing in my sitemap (or menus, breadcrumbs, etc).  This would be a simple change to source. Fortunately, since the system is so pluggable, I was able to just code up my own "URLFriendlyNodeKeyGeneratror" and plug it into the web.config. Again, nice work Maarten.

Dec 10, 2010 at 4:12 PM

I've actually deployed mixed nodes into production, with the above change, and things are working nicely. So, I tried to solve the "It actually works if you leave off the '~'." problem, since it's a requirement in my project. It comes down to a very simple change in the MvcSiteMapNode class, in the getter for the url property. Currently, it says:

if url is not null, return the url, else instantiate the URLResolver, and return the resolved URL.

First, I think it be better to move this "if not null" logic into the DefaultURLResolver. That way, I can implement my own URLFriendlyURLResolver to resolve these relative URLs. Since the check is done in the MVCSiteMapNode, there's no way for to override that behavior.

Second, I think what I'm doing in my URLFriendlyURLResolver should be part of the DefaultURLResolver. That is, instead of just returning the url, the system should check if the url starts with a ~, and if so, use System.Web.VirtualPathUtility.ToAbsolute() to resolve the url.

I've made this change in my local branch, and it works. But, I'd love to see this change in the trunk.

Coordinator
Dec 21, 2010 at 12:57 PM

Can you share your modifications? I'll happily commit these to the actual sources.