DISCLAIMER: This post is provided AS IS with no warranties and confers no rights. This is not an official Microsoft solution.
In the past couple years, I’ve often gotten the question “how can I effectively find sites (collections) based on enterprise metadata?”. For example, we may want to find all projects based on the organizational hierarchy, or the enterprise may have major company pillars that projects are based on, or to find all ‘XYZ-related’ projects, etc.
With SharePoint 2007, you could use the Site Directory feature which was providing a limited single-dimension listing site collections. However, it doesn’t scale very well to 1000s of site collections and it’s not securely trimmed. This feature is removed from SharePoint 2010 (except for upgrade scenarios).
My goal was to provide something for both 2007 and 2010 that brings more features and value. Essentially, the ability to define metadata at the feature level (metadata for the whole organization), the site definition level (metadata for the template), and at the provisioning level (metadata based on provisioning questions). Furthermore, site owners can edit property values through a standard web part on the site’s home page – with the ability to have read-only properties that are (re-)defined programmatically or through the feature. Last, but not least, since the metadata is added directly on the site’s page, the results are securely trimmed to what your users can actually see.
The solution is effectively simple: provide a metadata definition that a web part can read, add META tags to the home page, and allow for user editing. Search will be able to index those META tags from which administrators can create Managed Properties. From there, the standard search results can then be refined (2010), or faceted (2007 with the Faceted search component from CodePlex, http://facetedsearch.codeplex.com/). You can decide to provide custom interfaces with standard SQL Search development.
The solution logically resembles this:
Physically, the solution requires a somewhat complex metadata definition that is essentially a class that is serialized in XML and stored in the SPSite.RootWeb.AllProperties. This XML can be brought by the Site Definition or Feature properties, from which the Feature Receiver will read the properties and add them to the property bag; or it can be added through simple custom code. This definition is complex due to providing features such as multilingual display names, allowing for read-only properties, etc.
Here’s an excerpt of the sample Feature.xml:
<Feature Id="3aba9d3d-228a-443d-85b3-1f35d8aa6858"
Title="[Maxime Bombardier] Site Collection Metadata Sample"
Description="This is a feature that samples how to use the MaximeBSiteCollectionMetadata feature receiver and web part."
Version="12.0.0.0"
Hidden="FALSE"
Scope="Site"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/"
ReceiverAssembly="MaximeB.SharePoint.SiteCollectionMetadata, Version=1.0.0.0, Culture=neutral, PublicKeyToken=501530d13e13b1c5"
ReceiverClass="MaximeB.SharePoint.SiteCollectionMetadata.MaximeBSiteCollectionMetadataFeatureReceiver"
>
<ActivationDependencies>
<ActivationDependency FeatureId="6ede1ea7-4396-4cbc-b3f2-a757ca203463" />
</ActivationDependencies>
<Properties>
<Property Key="MetaDef-ConfidentialInformation" Value="<?xml version="1.0" encoding="utf-16"?>
<SiteCollectionMetadataDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>ConfidentialInformation</Name>
<AllowEditing>true</AllowEditing>
<DataType>TrueFalse</DataType>
<Value>true</Value>
<Choices />
<DisplayNames>
<SiteCollectionMetadataDisplayName>
<Code>1036</Code>
<Text>Information confidentielle</Text>
</SiteCollectionMetadataDisplayName>
<Code>1033</Code>
<Text>Confidential Information</Text>
</DisplayNames>
</SiteCollectionMetadataDefinition>" />
<Property Key="MetaDef-Region" Value="<?xml version="1.0" encoding="utf-16"?>
<Name>Region</Name>
<DataType>Choices</DataType>
<Value>North America</Value>
<Choices>
<string>North America</string>
<string>Europe</string>
<string>Canada</string>
</Choices>
<Text>Region</Text>
<Property Key="MetaDef-ProjectName" Value="<?xml version="1.0" encoding="utf-16"?>
<Name>ProjectName</Name>
<DataType>Text</DataType>
<Value>Site Collection Metadata Project</Value>
<Text>Nom de projet</Text>
<Text>Project Name</Text>
<Property Key="MetaDef-Model" Value="<?xml version="1.0" encoding="utf-16"?>
<AllowEditing>false</AllowEditing>
<Value>Collaboration Team Site by Maxime</Value>
<Name>Model</Name>
<Active>true</Active>
<Text>Model</Text>
<Text>Modele</Text>
</Properties>
</Feature>
The complexity of the definition comes from the limitation of storing in the AllProperties property bag : it’s a simple name/value collection so I need to store text. If you look carefully, the definition is actually encoded Xml with the following properties: Active, AllowEditing, DataType, Value, Name, Choices, and DisplayNames.
Note: you need to paste it as-is, I had some issues when adding spaces/tabs.
At the site definition, it’s basically the same concept:
<SiteFeatures>
... removed ...
<!-- Site Collection Metadata -->
<Feature ID="6ede1ea7-4396-4cbc-b3f2-a757ca203463" />
<!-- Site Collection Metadata Sample -->
<Feature ID="3aba9d3d-228a-443d-85b3-1f35d8aa6858">
<Properties xmlns="http://schemas.microsoft.com/sharepoint/">
<Property Key="MetaDef-SiteOwnerName" Value="<?xml version="1.0" encoding="utf-16"?>
<Name>SiteOwnerName</Name>
<Value>Maxime Bombardier</Value>
<Text>Site Owner Name</Text>
From a custom code perspective, I provided managers to create, serialize, and deserialize these properties, and I also provide a simple Windows application from which you can define your properties, copy them to clipboard, and paste them in your Site Definition or Feature properties. These managers can be found with the namespace MaximeB.SharePoint.SiteCollectionMetadata.SiteCollectionMetadataDefinitionManager. If you create a MaximeB.SharePoint.SiteCollectionMetadata.SiteCollectionMetadataDefinition and pass it to the GetStringFromMetadata method, you can store the returning value in the SPSite.RootWeb.AllProperties with a key that starts with “MetaDef-“ and it will automatically work with the Web Part.
The solution supports for these data types:
The solution code can be found here: while the Web Part’s WSP can also be found here : . Note that the solutions are with Visual Studio 2008 as I needed the solution to work with SharePoint 2007. I also used WSPBuilder 1.0.6 : http://wspbuilder.codeplex.com/.
The solution contains the following projects:
Here’s what the Windows Application looks like:
Here’s a quick list of properties that can be practical:
(if you have more, add to comments!)
The flexibility of the model is practical. Some enterprise may use a common template for projects, but they want to have a different look per business divisions, and they’d like to target content to each of them. You could either have a custom provisioning process, or a custom site definition that defines which business division it’s in, and your ‘content/communication’ web part would be able to use the values and target content accordingly.
Note that you’ll have to create Managed Properties, and/or make the properties searchable, to use them with Search. Also, when you add a new Managed Property, it requires a Full Crawl until it takes effect on all pages. However, any updates on the metadata will be picked through an incremental crawl.
When the feature’s activated, it will go through the feature and site definitions to sync properties. If the property is already defined, and it allows editing, the definition will be updated but the value will remain the ‘old’ one. If the property doesn’t allow editing, the definition and value will be updated.
When the feature is deactivated, the definitions will remain, however, the Active property will be set to False, effectively removing all META tags upon a subsequent crawl. Reactivating the feature will reset the definition to Active by default.
Last, a recap on what you need to do :