Please note that all new SharePoint related content is now hosted on the blog at www.muhimbi.com.
Recently I was looking into what the best way is to store settings centrally in SharePoint. Not just for a single Site Collection, but rather at the Farm and Web application level.
Sure, we could mess about in the web.config, which gets messy if the settings can be modified from a SharePoint screen, or use the ‘Settings’ property bag, which is available on Farm, Site as well some other objects, but this doesn’t provide much granular control in more complex scenarios.
So, enter the Hierarchical Object Store (HOS). The HOS allows settings or other kind of data to be stored for nearly every existing SharePoint object that inherits from SPPersistedObject, which is pretty much everything. As this article is not about programming the HOS, check out this very simple example by Maurice Prather.
Microsoft’s guidance and documentation on this subject is pretty thin, so I managed to corrupt the HOS within hours which had all kinds of nasty side effects such as not being able to call SPFarm.Update any more.
Great, so I have managed to muck up my SharePoint installation and get all kind of very generic error messages such as ‘Security Exception’ and the somewhat more descriptive
“The platform does not know how to deserialize an object of type Muhimbi.Licensing.SharePoint.LicenseStore. The platform can deserialize primitive types such as strings, integers, and GUIDs; other SPPersistedObjects or SPAutoserializingObjects; or collections of any of the above. Consider redesigning your objects to store values in one of these supported formats, or contact your software vendor for support. at Microsoft.SharePoint.Administration.SPAutoSerializingObject.
DeserializeBasicObject(XmlElement xmlValue)”
What I could have done to resolve this is to restore the previous day’s backup (your are making backups right!) of the configuration database, but what would be the fun in that? I would learn very little about what is going on under the hood.
After investigating the schema of the Config Database it became clear that HOS information is stored in 2 tables named ‘Classes’ and ‘Objects’. Similarly to C#, records in the Class table define some meta information about the makeup of a Class and the Objects table contains instance data for the class, basically the Object.
By Querying these tables for the type specified in the error message above I was able to find and delete existing instances of the corrupted data.
SELECT Id, BaseClassId, FullName FROM Classes where FullName like ‘Muhimbi%’
SELECT Id, ClassId, ParentId, Name, Status, Version, Properties FROM Objects WHERE Name LIKE ‘Muhimbi%’
Note that the Object table may also return some WSP files, don’t delete these. Always make sure that entries are removed from Objects before removing them from Classes as there is some referential integrity checking going on.
After cleaning up the existing entries in these tables the error messages I received after calling Update on any SPPersistedObject changed from SecurityException to the more descriptive Deserialization error listed above. Clearly something was still finding a reference to the offending type.
Some further investigation revealed that the Farm also has an entry in the Objects table. The Properties field for this entry stores a large blob of XML containing a reference to our dodgy HOS type. We stored our information using SPFarm as the parent, if you have used a different parent then just perform a ‘Like’ search for you type name in the Objects.properties field.
Selecting the Farm object works as follows:
SELECT * From Objects where ClassId = ‘674DA553-EA77-44A3-B9F8-3F70D786DE6A’
The Properties field contains the following XML blob. The relevant section has been highlighted in red.
<object type="Microsoft.SharePoint.Administration.SPFarm, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"> <sFld type="Int32" name="m_PersistedFileChunkSize">4194304</sFld> <fld name="m_PairConnectionString2" type="null" /> <fld type="Microsoft.SharePoint.Administration.Pairing, Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" name="m_Pairing">None</fld> <sFld type="Boolean" name="m_SqmEnabled">True</sFld> <sFld type="Boolean" name="m_WatsonEnabled">True</sFld> <sFld type="Boolean" name="m_DownloadErrorReportingUpdates">True</sFld> <sFld type="Boolean" name="m_bUpgradeFinalized">True</sFld> <sFld type="Boolean" name="m_bCommandLineUpgradeRunning">False</sFld> <sFld type="Boolean" name="m_reghostOnUpgrade">False</sFld> <sFld type="Guid" name="m_clsidExternalBinaryStore">00000000-0000-0000-0000-000000000000</sFld> <fld type="System.Collections.Generic.Dictionary`2[[System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Version, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="m_Versions"> <sFld type="Guid">00000000-0000-0000-0000-000000000000</sFld> <sFld type="Version">12.0.0.6318</sFld> <sFld type="Guid">77e7f90e-1989-46c2-ad65-361a53dcb2e0</sFld> <sFld type="Version">3.0.4.0</sFld> <sFld type="Guid">6ac833ea-3f8d-46b6-8b30-92ac4553a742</sFld> <sFld type="Version">12.0.1.0</sFld> </fld> <fld name="m_UpgradeContext" type="null" /> <fld type="System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="m_UpgradedPersistedFields" /> <fld type="System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="m_Properties"> <sFld type="String">Muhimbi.Licensing.Configuration.LicenseStore</sFld> <fld type="Muhimbi.Licensing.SharePoint.LicenseStore, Muhimbi.Licensing.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c9db4759c9eaad12" /> </fld> <sFld type="String" name="m_LastUpdatedUser">MUHIMBI\jeroen.ritmeijer</sFld> <sFld type="String" name="m_LastUpdatedProcess">w3wp</sFld> <sFld type="String" name="m_LastUpdatedMachine">GBSAVDWS002</sFld> <sFld type="DateTime" name="m_LastUpdatedTime">2008-12-08T15:03:02</sFld> </object>
Basically what you are looking for is a ‘fld’ element with a name attribute of ‘m_Properties’. As my farm object only contained my own HOS data I replaced the section marked in red with:
<fld name="m_Properties" type="null" />
After a quick IISRESET, just to be sure, everything worked fine again.
Note that the entire HOS seems immature, brittle and not very well thought through. I recommend you only use it if you really need to. If at all possible use the Properties collection on any of the existing objects. In the end I ended up creating a very simple object that only stores one value in the HOS, this value contains an XML Serialised object hierarchy of what I really want to store.
Another day in my life gone that I will never see back.
Please note that all new SharePoint related content is now hosted on the blog at www.muhimbi.com.
Recent Comments