Provisioning Content Query Web Part querying subsites in a structured and repeatable way

, , , , ,

Today, while working on a brand new SharePoint Web Content Management (WCM) solution, I’ve faced quite a challenge: I needed to provision a Content Query Web Part (CQWP) which would query subsites of the current site using a custom Site Definition. Each time user would create a site using that Site Definition, he would get on the home page an aggregation of the content from all underlying sites. It’s more challenging than it sounds and you won’t know it unless you had to do it yourself once.

Various scopes querying data using the Content Query Web PartThe Content Query Web Part allows you to query content using one of the three scopes. You can query the content from the whole Site Collection, from a particular web and its children and from a particular list. Looking at my requirement, I had to use the second option.

By default the CQWP queries the whole Site Collection. Using some criteria this option is sufficient in many situations. I couldn’t use that option in my situation however because: a) it would perform too bad querying a couple of thousand pages; b) it would return more content than needed.

The second option seems to be just the right thing: by passing the URL of a web, you can make the Content Query Web Part query all the content within that particular web and all the underlying sites as well. The problem is that you need to pass the server relative URL of the site you are about to create.

Tokenizing the WebUrl property

After looking for a while on how to obtain the URL of the current site inside the ONET.XML file, I have found out that you are actually allowed to use the ~Site token to point to the current site. At some point (I’m not sure whether it’s the SharePoint site provisioning engine or the Content Query Web Part self) the token is being replaced with the site relative URL of the current site – just as the CQWP requires.

Tokenizing the WebUrl property of the Content Query Web Part using the ~Site token

Alternatives

Using the AllUsersWebPart element is not the only way to provision a Web Part. Recently there was quite some discussion about the whole idea of the Site Definition and whether it is right or wrong to use them. Personally I feel quite comfortable with using the standard SharePoint approach to deploy things. In all the time I’ve been working with SharePoint I think I’ve found my way around the whole concept and I know what I can customize and what I should leave untouched.

Provisioning the Custom Query Web Part using Features

Alternatively to the approach I chose you might want to use something else. First of all you might choose to create a Feature which would provision the web part upon activation. While this approach is definitely plausible and widely used, it doesn’t cope with my idea on structured and repeatable deployment. While you can reuse the functionality across many sites, provisioning web parts programmatically lacks overview to me. I just don’t like the idea of mixing configuration with custom code. To me XML provides more overview and context about the configuration of the particular page.

Provisioning Web Parts using Event Handlers

You could of course use the concept of Event Handler to provision the Web Part. Each time a Publishing Page is created, it would trigger your Event Handler. Using some custom logic you could determine whether to provision an instance of the particular Web Part or not. While this approach provides you with some extra control it shares the lack of overview with the approach I previously mentioned.

Summary

Provisioning Web Parts in a structured and repeatable way allows you to track the currently used configuration and improves the overall manageability of the SharePoint solution. By tokenizing the settings of the Content Query Web Part you can dynamically provision its instances which meet your requirements without mixing the configuration with custom code.

Possibly related posts

8 Responses to “Provisioning Content Query Web Part querying subsites in a structured and repeatable way”

  1. Jeremy Thake Says:

    I have written a series and one of the parts goes into detail on how to provision a CQWP via API code in a Feature
    http://wss.made4the.net/archive/2008/06/07/solution-development-in-sharepoint-2007-part-5.aspx

  2. Waldek Mastykarz Says:

    Thanks for the link, Jeremy :)

  3. Paul Brown Says:

    Humm – this doesn't work for me, which is a pity as it looked a very promising solution to a problem I'm having.

    Of course the chances are that I'm doing something wrong, but if I understand you correctly this is a fairly simple concept.

    I edited my .webpart as per your screenshot above to have '~Site' as the WebUrl, which when it's imported into my layout becomes
    Other stuff here

    The trouble is, in my output page, I get nothing. If I then replace WebUrl="/MYSUBSITE" then it works as expected (except my layout is then hard coded to a specific subsite, i.e. the problem I'm trying to get around.

    Is there something obvious I'm missing?

  4. Paul Brown Says:

    That doesn't make as much sense as it should, as my pseudo-markup's been removed. It should say something like the webpart has in its XML in the page layout -

    [ PublishingWebControls:ContentByQueryWebPart ... WebUrl="~Site" ... ]
    Other stuff here
    [/PublishingWebControls:ContentByQueryWebPart]

  5. Waldek Mastykarz Says:

    @Paul: As I've mentioned I've used the token inside ONET.XML. That's where the web part is being provisioned. From what you're saying you've been trying to use the token within the CQWP deployed as a web control. I don't think it will work as the token is being replaced during the deployment and not on run-time.

  6. Mohamed Hachem Says:

    Actually, when using onet.xml file for deploying solution. if you put the webpart within module and set WebUrl property to ~site top level url will be returned dynamically.

    It is not the case when you add webpart mannually or you deploy it using wsp builder because only the module context allow for the interpretation of the top level url.

    Since I am using onet.xml it is an awsome solution hope that other people will use

  7. Waldek Mastykarz Says:

    @Mohamed: While you could base your provisioning process fully upon ONET.XML, it has some serious drawbacks.
    First of all you would have to define in ONET.XML ALL the different Site Definitions. As working with ONET.XML isn't easy, it would take a lot of time to do it. Additionally you cannot really debug ONET.XML: it either works or doesn't. And if it breaks the ULS log is the only place where you can look for errors.
    Then ONET.XML is not updateable: according to the SharePoint SDK modifying a Site Definition after instances of it have been provisioned is not supported.

  8. LOVE_MOSS_NOT Says:

    Thank you! really helpful.

    As always, pulling my hair with this wonderful and powerful product.

Leave a Reply

Security Code:

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS
Copyright © 2007 - 2010 Waldek Mastykarz

Creative Commons License