New ASP.NET 2.0 SQL Site Map Provider

Jeff Prosise has a written a great sample and article for the February edition of MSDN magazine that walksthrough the new SQL Server based provider he built for the ASP.NET 2.0 Site Navigation System.  This enables you to store your site map structure in a database instead of using the default XML Provider that comes default.  Enabling it within an ASP.NET 2.0 site is as simple as configuring the provider in your web.config file -- no code needs to change in order to take advantage of it (and you can databind any page control to it using the new SiteMapDataSource control).

What is really cool about his provider is that it also uses the new SQL Cache Invalidation feature to cache the sitemap structure in-memory within ASP.NET (avoiding the need to hit the database each request to retrieve the data), but automatically regenerate it anytime the site-map structure changes in the database (ensuring that your site structure is always up to date).

You can read all about it and download the code from here.

Here are a few of my past posts on the new ASP.NET 2.0 Site Navigation system if you are interested in learning about it more:

Hope this helps,

Scott

 

Published Wednesday, January 11, 2006 5:59 PM by ScottGu

Comments

# re: New ASP.NET 2.0 SQL Site Map Provider

Sunday, January 15, 2006 11:52 AM by Russ Helfand
Perfect timing. A local business has been asking about if a site map could be added to their existing ASP.NET 2.0 web site. The code provided by Jeff Prosise will make this super-easy.

While working up a demo for this client, I ran into one small glitch. I couldn't seem to get the sql cache dependency system to work against a SQL Server 2005 Express (MDF) database. It seems that you have to turn on the service broker ala http://msdn2.microsoft.com/ms166086.aspx. I ran into problems, however, trying to execute this ALTER DATABASE command against my MDF. I tried doing it from an SQL command panel in VWD's database explorer. I also tried doing it programmatically by executing an SQL command within the site map provider's Initialize method. I seemed to have a little luck doing it from a SQL command window in SQL Server Management Studio Express CTP but ultimately it was not successful enough to allow my web app to work.

It's not a huge deal since I can easily turn off the caching when using the MDF (rather than the full SQL Server database instance). A few tweaks to the web.config is all I need. Still, it would be awesome if there were a way to play with the sql dependency caching feature using a fully local MDF database.

One more thought... it would be cool to magically prepopulate the SiteMap table with the heirarchy of folders/pages in the web app itself. This would provide the site's admin a good starting point from which to prune or tweak the data to differentiate the actual from the logical presentation of the site map. Currently the logical representation has to be built up in the site map table in the database "by hand" (from nothing). That's OK but it would be super-helpful to somehow have it prepopulated with all (or a segment) of the physical structure of the site.

Next task for me: build the admin page that allows the site map records to be pruned/tweaked. Fun stuff!

# re: New ASP.NET 2.0 SQL Site Map Provider

Monday, January 16, 2006 6:34 PM by Roger
Scott,

I apologize again if my question creeps out of the scope of your article:

I have seen plenty of examples of creating site map nodes from a database, however in my case I am also storing localization data.

So, I have a site map provider that is loading the nodes from my database, but now I need to load the language specific titles and descriptions from my database as well.

It seems the most flexible overload for the SiteMapNode constructor allows for passing an explicit name-value-pairing of resource idenfifiers, or a single implicit key:

new SiteMapNode(SiteMapProvider provider, string key, string url, string title, string description, IList roles, NameValueCollection attributes, NameValueCollection explicitResourceKeys, string implicitResourceKey);

I would be happy to use either parameter, however I have not had any luck finding examples on how to generate string resources dynamically.

If you could point me in the right direction (or tell me if I'm trying to do something impossible) it would be a big help!

Thanks again,
Roger

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, January 17, 2006 7:50 PM by scottgu
Hi Roger,

I personally don't know as much about how our localization features work as I should. But here is what I got back from my team:

From the point of view of the SiteMapNode, the two different approaches of referencing localized data are:

Implicit resources: Set the implicitResourceKey parameter of of the SiteMapNode's constructor when constructing node instances. Internally the node will cause ASP.NET to load a resource file based on the value returned from the provider's public ResourceKey property. For XmlSiteMapProvider this name is the filename of the sitemap file. So if the sitemap file is called "web.sitemap", the SiteMapNode will ask ASP.NET to look in web.sitemap.NN.resx where NN is the culture identifier. The fallback resource file would be web.sitemap.resx. Once the appropriate resource file is loaded, the SiteMapNode will ask for the resource with a name that is a combination of the implicitResourceKey parameter from the constructor and the name of the node attribute that is being localized. For example, for the "title" attribute on <siteMapNode />, if "resourceKey" is set to "Category", then SiteMapNode will ask for the localized value called "Category.Title".

Explicit resources: When constructing a SiteMapNode, add localization information into the explicitResourceKeys parameter. This is a NameValueCollection and expects to have each entry in the following form:

key = name of the SiteMapNode attribute that will be localized. For example "title" for the node's Title property.

value = A string array with two entries: array[0] contains the root name of the resource file; array[1] contains the key name used to lookup the data in the resource file. For example, if you wanted to store localized information in resource files called foo.resx, foo.fr.resx, etc.... then array[0] would be set to "foo". If the the actual localized data was keyed off of "TitleKey", than array[1] would be set to this value. When SiteMapNode needs to retrieve the localized value for one of its properties it looks in the NameValueCollection using the property name as the key. It then uses the resultant string[] to ask for the appropriate resource file to get loaded and indexes into the resource file using the second value from the array.

They also then suggested checking out this site to learn how you could build a localization provider that is database backed: http://www.leftslipper.com/ShowFaq.aspx?FaqId=9

Hope this helps,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Monday, February 06, 2006 4:06 PM by Danny Chen
One thing I'm noticing a lot of users ask for at the ASP.NET forums is an updatable SiteMapProvider. The invalidation features of ASP.NET can also be applied file changes. In this context, the same strategy Jeff uses to invalidate and refresh his SiteMap can be applied to file changes as well.

In short, the example from Jeff can also be used as a great model for creating updatable SiteMapProviders. I hope a lot of users can take advantage of this to improve their own custom SiteMapProviders from caching to dynamically updating. This doesn't need to only be applied to SQL.
--
Danny

# Data Tutorial #2: Building our Master Page and Site Navigation Structure

Friday, June 23, 2006 2:23 AM by ScottGu's Blog
June 22nd 2006 Update: We've now published a whole series of new data tutorials based on this origional...

# re: New ASP.NET 2.0 SQL Site Map Provider

Monday, July 24, 2006 5:26 PM by Steve
I am struggling to find a way to declare a siteMap that has a dynamic location for the sitemap xml file. Can I declare the siteMapFile at runtime or dynamically add a provider somehow? Any help is greatly appreciated. Thanks Steve

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, July 25, 2006 2:05 PM by Bertrand Le Roy

Steve: the site map provider can be changed anytime on the SiteMapDataSource. Does that help?

# re: New ASP.NET 2.0 SQL Site Map Provider

Friday, September 22, 2006 12:36 PM by Anders Djursaa ad@kimik-it.gl
I am trying to make som SiteMapNodes - and to make use of explicit localization. Following your exelent advice - I have one problem. How do you construct a NameValueCollection that contains an string[] as value? The NameValueCollection.Add() only accepts 2 stings. Regards Anders Djursaa

# re: New ASP.NET 2.0 SQL Site Map Provider

Sunday, September 24, 2006 12:06 PM by ScottGu

Hi Anders,

I don't see an overloaded method on NameValueCollection that accepts a string.  What I think you'll have to-do is to just call the Add method multiple times.

Hope this helps,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, October 10, 2006 11:26 AM by ScottGu

Hi Ken,

Can you send me email directly with this question?  I will then loop in a few folks who know more about this to help.

Thanks,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, October 10, 2006 4:23 PM by Ken
Hi Scott, Although I had emailed you I just found the answer to my problem: http://forums.asp.net/1424306/ShowThread.aspx#1424306 But thanks for your time anyway :-)

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, October 17, 2006 10:31 AM by eru
Hi I ran into a problem using the SqlSiteMapProvider. The StaticSelectedStyle is unfortunately not applied as expected. What is required that this style is applied? Thanks in advance for your help. Regards, eru

# re: New ASP.NET 2.0 SQL Site Map Provider

Friday, November 10, 2006 3:29 PM by Marcelo
Jeff article is very useful. I have tweaked it a bit so the SiteMap table handles menus for multiple web applications. Prior and after the code changes I am finding some problems retrieving the data from the database (SQL Server 2005 locally installed) Sometimes it works well. Sometimes the BuildSiteMap method gets called multiple times (6, 7, 8 times) before rendering the page. Some times the menu control is not rendered at all. When it works (meaning that the menu control gets rendered) I have tried changing the DB and then refreshing the page. The page refreshes with the old values. Because of this I have played with setting it to true and false, no difference. Any ideas why this is behaving like this?

# re: New ASP.NET 2.0 SQL Site Map Provider

Thursday, November 16, 2006 12:02 PM by Marcelo

I am still having problems with the SQL Site Map Provider. It only calls the sproc (in BuildSiteMap()) only once. I can logout or even re-start the web app. and it will still use old data. I have disabled SQL Caching on the database by running aspnet_regsql -dd and I have also removed the attribute sqlCacheDependency from the web config. What else do I need to do to force the SqlSiteMapProvider class to initialize every  time?

# re: New ASP.NET 2.0 SQL Site Map Provider

Sunday, November 19, 2006 4:47 PM by ScottGu

Hi Marcelo,

If you can send me an email, I will loop you in with someone on my team who might be able to help.

Thanks,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, November 28, 2006 11:31 PM by jds

I'm working with a custom sitemap provider and am wondering if there is a way I can access session data from the BuildSiteMap method?

In the above posts there was a discussion about localization, how would one access the locale for the current session?

Any helpful comments would be appreciated.

Thanks

# re: New ASP.NET 2.0 SQL Site Map Provider

Wednesday, November 29, 2006 1:12 PM by ScottGu

Hi JDS,

You might be able to access Session information by writing code like this:

HttpContext.Current.Session("somevalue")

I'm not 100% sure where/when the above method gets called - so am not sure if the session data is always there or not.  But this might get you started down the right path.

Hope this helps,

Scott

# reloading problems as well

Wednesday, November 29, 2006 1:29 PM by Todd

Hi Scott,

I am having the same problems as Marcelo. No matter what I do I can not reload the site map. Did you find out any information from your team that could help with this situation?

Thanks,

Todd

# re: New ASP.NET 2.0 SQL Site Map Provider

Saturday, December 02, 2006 6:02 AM by Donrajah

how would it be possible to Filter the nodes if i use this custom Site Provier.for eg if i have 2 master pages but the contents need to be varied .

thnx

don

# re: New ASP.NET 2.0 SQL Site Map Provider

Saturday, December 02, 2006 6:49 PM by ScottGu

Hi Donrajah,

You should be able to use the standard SiteMap mechanisms for varying the content regardless of which SiteMap Provider you use.

Hope this helps,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Saturday, January 06, 2007 5:03 AM by Greg

Hi,

I have this working on my website, but now I need to add another menu for the administration section. What is the best approach to achieve this?

Should I try and create another provider and use 2 sp's e.g. GetSiteMap and GetAdminSiteMap or just use one sp and provider and try to filter the items in the buildsitemap method?

Thanks in advance.

# re: New ASP.NET 2.0 SQL Site Map Provider

Saturday, January 06, 2007 6:23 PM by ScottGu

Hi Greg,

You can actually register multiple SiteMap providers in your web.config file - and then point the SiteMapDataSource control at the provider you wish to use.  So that would be one option to use.

Hope this helps,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Tuesday, January 09, 2007 6:52 AM by smeja

Hi Scott,

I am having the same problems as Marcelo and Todd. I can't reload the site map. Can i force a reload ie. at login? Any ideas?

Thanks,

smeja

# re: New ASP.NET 2.0 SQL Site Map Provider

Wednesday, January 10, 2007 1:52 AM by ScottGu

Hi Smeja,

Do you have the SQL Cache Invalidation feature enabled with it?  I believe this will automatically invalidate the cache when the database contents change.

Thanks,

Scott

# re: New ASP.NET 2.0 SQL Site Map Provider

Wednesday, March 14, 2007 1:04 AM by Romie

Hi Scott,

I have multiple sitemapproviders and the sitemapdatasource is placed on the masterpage.  I set the sitemapprovider depending on the state of the user that logs in.  This works perfectly, however when I change pages (all my pages are content pages) the sitemapprovider defaults to the original. Do you know why?

# re: New ASP.NET 2.0 SQL Site Map Provider

Monday, March 19, 2007 3:14 AM by ScottGu

Hi Romie,

The master page runs on each request - so by default it will revert back to its default setting when the user navigates to a new page.

You'll want to set this value on each page request to the application.

Thanks,

Scott