OdeToCode IC Logo

Sitemap Macro

Wednesday, November 30, 2005

I wrote a Visual Studio macro to walk an ASP.NET 2.0 project and create a web.sitemap based on the physical layout of files.


The macro requires a reference to System.Xml.dll. The macro won’t overwrite or synchronize an existing web.sitemap file, it’s only meant to save some typing if you have an existing project and want to add a sitemap. Once the macro creates the sitemap, you can go in and modify the titles, descriptions, and layout.

Update: Fixed the macro to work with IIS based projects, and added Dan Kahler's suggestion to prompt user to overwrite existing file.

Keyvan Nayyeri Wednesday, November 30, 2005
Well done;
But a question. As you wrote here:
Private ReadOnly validSiteMapNodes() As String = {".ASPX", ".HTML", ".HTM"}
By default it tries to find all pages and add them to SiteMap file but if someone tries to add pages based on Queries he will be unsuccessful.
So probably each developer needs to write same Macro based on his Queries to generate his own SiteMap file? In most cased we have just one .ASPX page but handle many pages on it ;)
And another question: Why it's necessary to have a default start page for project to generate its SiteMap node? Maybe I try set my /Weblog/default.aspx page as default but my home page is /default.aspx file. Which file will be defined as my Home Page in SiteMap file?
scott Wednesday, November 30, 2005
Hi Keyvan:

Good questions. As I said, the macro only builds a sitemap based on the physical layout. If you do any URL re-writing, virtual path provider trickery, or query string magic - it won't know about those URLs. At least it gives you a starting point to copy and paste additional siteMapNodes - I was just looking to avoid some typing.

As for the default start page - the site map has to have a root <siteMapNode> to represent the top of the navigation tree. For me, the best way to determine the root node was just to look at the start page property. It's not a requirement for sitemaps in general.
Paul Litwin Thursday, December 1, 2005
I have been thinking that such a utility would be cool to create. And you beat me to it. Cool.

Okay at the risk of sounding like an idiot...I've never used VS macros before. How do I make use of your macro. I've been playing around with the VS Macros menus, IDE, explorer, etc. and am totally clueless. I want to use your macro but do not know what to do to use it.
scott Thursday, December 1, 2005
I fixed one little bug and uploaded a new version.

Paul, I should have left installation instructions:

1) Open macro explorer (Alt + F8)

2) Right click MyMacros, select New Module (the module name can be anything)

3) Right click the new module and select Edit

3) Replace the contents of the new module with the contents of SiteMapModule.vb

4) Right click References under MyMacros and add a reference to System.Xml

Hopefully that is enough to get you running. Now in the Macro Explorer window of VS.NET you can right click and run the macro...
scott Thursday, December 1, 2005
I learned something new -

In step 2 I said the module name can be anything.

Turns out, the name of the module must match the name of the Public Module definition inside.

In other words, I use

Public Module SiteMapModule
End Module

So the module itself must be called SiteMapModule. You can right click the module in Macro Explorer and select "Rename" if it's not named properly..

Paul Litwin Thursday, December 1, 2005
That worked. Thanks!
Dan Kahler Thursday, December 1, 2005
Hey Scott, this is really handy - thanks! Works like a champ.

I've found a small modification that's useful to me:

Within the ProcesWebSite sub, I've modified the MsgBox line within "If HasSiteMap(...)" to ask if you'd like to overwrite the existing sitemap file (MsgBoxStyle.YesNo), and moved the Return statement inside this If block. This little tweak saves another step, especially if you're rapidly prototying page organization.

As always, EXCELLENT work.
scott Friday, December 2, 2005
Dan: I really thought you should run with it some more and create something that keeps the sitemap in synch with an existing project ;)
Kerric Friday, December 2, 2005
I tried to install and run the macro in VS2005

I had a problem running the macro and got the following error

URI formats are not supported.

When debugging the code, i noticed that you use the path of the web project and append the name web.sitemap. In VS2005 the path of the webproject is a url in my case to the my localweb server. Im not familiar with the framework for VS Studio is there another property which can find the physical path of the project?
scott Friday, December 2, 2005
Hi Kerric:

I'll have to investigate that one. I've only used the macro with a file system based project, not one hosted in IIS. It might be an easy fix (just use a different project property).
Scott Friday, December 2, 2005
Ok, updated file in place to work with IIS projects.
Bill Saturday, December 3, 2005
Are you good at every area of .NET or what. Wayyy cool man!
Neal Tuesday, January 24, 2006
This is awesome. How would you generate the web.sitemap upon page load? In other words how could I accomplish this without the macro?
scott Tuesday, January 24, 2006

You could use the same code that is in the macro to walk the filesystem and make a web.config file. I'd try to do this from Application_Start instead of a Page_Load.
Neal Tuesday, January 24, 2006
Could you plz give me an example?
Scott Wednesday, January 25, 2006
Actually Neal, after thinking about this, the proper way to generate a sitemap at runtime would be to write a custom provider. That's a little more than a simple example :)

There is a white paper on the topic here: msdn.microsoft.com/.../default.asp
Sharbel Wednesday, February 22, 2006
Hey Scott,

Nice Macro! I do have a little problem, it seems that the directories and filetypes listed in the validSiteMapNodes() and the excludeDirectoriesPrefix() are not being enforced correctly?

For example, in my /images directory, I have a bunch of .jpg/.gif/.png etc type files. An XML node is created for each one, however, no URL attribute is inserted, just a title. I would assume that the whole Node should be foregone?

Moreover, I edited the excludeDirectoriesPrefix() to include a few directories I didnt want crawled, but they still are crawled.

Are these known problems?
scott Thursday, February 23, 2006

I'm not aware of any problems - could it be a case sensitivity issue?
Robert J. Bullock Thursday, March 23, 2006
Dude, you just saved me 6-8 hours of annoying sitemap editing! THANK YOU!!!
Sal Wednesday, March 29, 2006
I 2nd the saving of time! Thanks!
Joel Reinford Monday, April 10, 2006

This macro is a real time saver. I suggest making the file extension list and excludeddirectory list non-case sensitive by using .StartsWith(name.ToUpper) in each of the two methods below. You're already forcing the item name to uppercase so it just makes sense to force the search string to uppercase too.

Joel Reinford
Data Management Solutions LLC

Private Function IsValidDirectory(ByVal item As EnvDTE.ProjectItem) As Boolean

If item.ProjectItems Is Nothing Then
Return False
For Each name As String In excludeDirectoriesPrefix
If item.Name.ToUpper().StartsWith(name.ToUpper) Then
Return False
End If
End If

Return True

End Function

Private Function IsValidFile(ByVal item As EnvDTE.ProjectItem) As Boolean

For Each name As String In validSiteMapNodes
If item.Name.ToUpper().EndsWith(name.ToUpper) Then
Return True
End If

Return False

End Function
ben Tuesday, May 2, 2006
error in code:

Dim dte1 As New EnvDTE.DTE
'For Each project As EnvDTE.Project In DTE.Solution.Projects
For Each project As EnvDTE.Project In dte1.Solution.Projects

scott Tuesday, May 2, 2006
Ben: You shouldn't need that code. You'll want a reference to the existing DTE, not a new one. What problem were you having?
Joseph Leonard Thursday, June 29, 2006
Can't get this to work. VS 2005 says following:
Private siteMap As XmlDocument Error "XmlDocument" not definded.

Also pressing F5 does nothing. No error messages and macro does not run.

Is there a walk-through on setting this up?
John Roberts Thursday, June 29, 2006
Instructions not correct for VS 2005:
I fixed one little bug and uploaded a new version.

4) Right click References under MyMacros and add a reference to System.Xml (There is no such choice after right clicking here. Unable to continue with setup.)

Also how does one RUN the macro?
Darin Monday, July 3, 2006
Any chance that this would work in Visual Studio 2003?
scott Tuesday, July 4, 2006

The macro itself might work in 2003 (I have not tried it), but the sitemap features are 2.0 only, so it may not be useful.
Sean Loughrey Saturday, October 14, 2006
This is a great utility. One thing I found is that this will not work if using the web application project add-in. I kept getting a '0' web-site processed message. To test this I created and empty web project and added my file and it worked perfectly. I think I need to change the webProjectKind As String = "{E24C65DC-7377-472B-9ABA-BC803B73C61A}" reference. Can anyone tell where to find the reference for this. Scott. Good work as always.
scott Monday, October 16, 2006

For now, you might just remove the code that checks for the project type. I'll try to get out an update that works with WAP this week.
Tatyana Monday, October 23, 2006
how does one RUN the macro? I do not see the option to run if right click on macro ...
Keith Wednesday, November 8, 2006
Tatyana: I noticed that Scott hasn't replied to your question yet, so I will help him out:

If you name the macro SiteMapModule (you have to name the module the same as the module name in the code), in your Macro Explorer, it will show the CreateWebStemap method under the macro. (If it doesn't, you don't have the module's name set correctly.) You can then right-click on the method (in this case, there is only one: CreateWebSitemap) and get the Run menu option.

Comments are closed.