Today my colleague Harmjan Greving pointed me to the Portal Navigation Properties Feature. I had never encountered this one before and as it turns out it is surprisingly undocumented by Microsoft.
So what does it do? Well, it’s a feature that comes with MOSS 2007 (unfortunately it isn’t included with WSS 3.0) that enables you to define per-site navigation settings in a declarative way. Until now I always used to write custom API code for this, that I executed from a feature receiver or a custom site provisioning provider.
The Portal Navigation Properties Feature itself is actually very simple. It contains no elements, but is only used to trigger the Microsoft.SharePoint.Publishing.NavigationFeatureHandler feature receiver, which does the real work, based on properties you specify. It is typically used from within a site definition file (ONET.XML), like this:
Using Reflector I found out the following properties can be used with this feature:
Property
Valid Values
IncludeInCurrentNavigation
True / False
InheritGlobalNavigation
True / False
InheritCurrentNavigation
True / False
ShowSiblings
True / False
IncludeSubSites
True / False
IncludePages
True / False
OrderingMethod
Automatic ManualWithAutomaticPageSorting Manual
AutomaticSortingMathod 1
Title CreatedDate LastModifiedDate
SortAscending
True / False
1 Please note the awful spelling error in “AutomaticSortingMathod”. Ofcourse this should have been “AutomaticSortingMethod”, but apparently someone at Microsoft forgot to run the spell checker over his/her code
If you’re querying SharePoint content using a CAML query from code it’s a good habit to always populate the SPQuery instance’s ViewFields property. Otherwise the returned SPListItem instances might not contain any data for certain fields and throw an exception when you try to access those fields.
Specifying ViewFields involves creating a string of CAML FieldRef elements. For instance if we want our query to return items that contain data for the Title, Created and ID field we use this:
As you can see there’s some overhead of boilerplate markup involved. I’ve written a small piece of code that I always use to make my life a little easier. Today I happened to post this code in a reply I wrote on the MSDN forums and also decided to submit it as Community Content to the official SPQuery docs on MSDN. Then I thought I might as well share it with you here. So here it is:
I’m planning on doing some posts about frustrating things I have encountered (and still do!) during my SharePoint development efforts. Here’s the first one:
Last year while working on a MOSS 2007 project for one of our customers I stumbled on what I thought was a bug in SharePoint 2007. I had created a custom list that was filled with Electronic Program Guide (EPG) information for the streaming video media that that site contained. I then created a Webpart that used ASP.Net AJAX to continually show the actual EPG information below the video stream.
In order to obtain the EPG items I used a CAML query to query the EPG list. The list was simply a custom list containing amongst others a column of type DateTime that was called "ProgramEnd". As the name suggests it contained the time the program ended. I then used the following code to create a query that was supposed to obtain the currently broadcasted item and all future items.
To my surprise this query always returned too many items. Further investigation showed that time part of the query seemed to be ignored completely, so it returned the items as if no time was specified! So instead of getting the current item and all future items it returned all items broadcasted for that day.
After wasting a lot of time debugging, using the U2U Caml Query Builder and looking for an answer / solution on the internet I gave up and wrote a quick hack around it, which fortunately wasn’t very difficult. It would just run the query and run the results through some additional code that checked the ProgramEnd DateTime field and filter out the wrong items, like this:
1: SPListItemCollection results = …; // The results from the query mentioned above
2:// Trim the results to only include the current and future items
3: List<SPListItem> trimmedItems = new List<SPListItem>();
Fortunately this worked just fine and the customer was happy. I was not…
Today while surfing the Net I stumbled on this entry in the MSDN forums, from which I learned it wasn’t a bug, but that you need to included the "IncludeTimeValue" attribute to the CAML query, like this:
If only I had known it was this simple… What bothers me is that this little, but very important attribute seems to be totally undocumented. I couldn’t find any information about it in the WSS / SharePoint SDKs.
Ofcourse once I knew what to look for I found someother blogs and forums mentioning this issue. It turns out the UCSharp blog had already blogged about this way back in October 2007, only a few months after I searched for it. Even Karine Bosch, U2U’s "CAML Girl" and author of the famous U2U CAML Query Builder, says she only recently found out about this. Fortunately she has included support for the "IncludeTimeValue" attribute in her latest version of the U2U Caml Query Builder, which I know a lot of SharePoint developers use to construct and test their CAML queries.
I also noticed that someone called puneetspeed has added some Community Content to the online SharePoint SDK’s SPQuery docs explaining this issue. So hopefully Microsoft will add information about the "IncludeTimeValue" attribute to the official SDK text in the near future.
Just arrived back from my visit to the Microsoft DevDays 2008 in Amsterdam. It was a great day and I’ve attended some interesting sessions.
I’ve uploaded the photos I took to my Flickr account, so check ‘em out. I’ve also uploaded a small video of the “Holland Sport” bicycle race track we had at our booth. Check it out:
It was a very tiring day and I’m going to get some sleep now. I’ll blog about some more about the DevDays later on…
Tomorrow (well… in a couple of hours actually) I’m off to Amsterdam for the Microsoft DevDays 2008. This year I’m only going to attend the first of the two days. My employer, Atos Origin, is a Platinum sponsor for the event and we’ll be there with a big booth.
At our booth you’ll be able to compete in a fun bicycle contest and perhaps win one of the six XBOX 360 consoles we are giving away! Hope to see you there. I’m scheduled for booth duty on thursday morning. Yes, that’s during David Platt’s great keynote on “Why Software Sucks”. Fortunately I’ve already seen this one during TechEd Developers 2007 in Barcelona last year and I also own an autographed copy of his book on the topic. But still I’m going to try to sneak away from the booth for a while
As for my SharePoint interests I’m hoping to get a chance to speak with Jan Tielens and Patrick Tisseghem, who are both scheduled to speak at the event. I’ve got some burning questions about Custom Security Trimmers that I hope Patrick can answer.
Oh, and ofcourse I’ll take my digital camera and see if I can take some nice pictures of the event and post them here.