Programming MOSS can be painful and tedious. It really can.
I'm not talking about the feature-files, element-files or all those other manifest-files you need to make and maintain. I'm not talking about the endless directory-structures which you have to set up exactly correct.
I am talking about the pitfalls when working with Sharepoint programatically.
We have CAML and God knows writing CAML makes one long for any other way to process data, including using VBScript to iterate multi-dimensional arrays.
This initial pain can be somewhat lessened though. You can use existing CAML.NET, you write your own wrapper-classes or if your needs are 100% static, you might stick to the U2U CAML Query Builder to generate queries which you copy and paste.
This is however not near covering all possible pitfalls related to CAML. The execution of CAML-queries are highly unpredictable and you should pay extreme caution when using them.
The user-data entered make break your query which worked fine in testing. Escape and make entities out of any user-supplied data.
If your CAML-syntax is wrong when using SPSiteDataQuery-object, you will not get an error. You will get an empty result-set. Do not automatically assume that your where-clause is wrong: Check the entire syntax.
If your CAML-syntax is wrong when using SPQuery on SPList-objects, once again (I am told) you will not get any errors, but the query-filtering will get ignored and you will get the full contents of the list. If your intention is to modify list-content, you risk corrupting immense amounts of data.
It is also worth noting that even though certain columns appears in your result-set, this does not automatically mean they can be used for filtering. Trying to filter on SiteId for instance will in fact, once again, give you a empty result-set, and again no errors.
In these case, if you have a rowlimit to obey and need to do filtering, you will have to do pessimistic row-estimates and post-filtering on the returned result-set.
Datatypes are not what they seem and are not handled consistently. This becomes painfully obvious once trying to use SPSiteDataQuery result-sets together with the Sharepoint object-model for navigation and manipulation.
With SPSiteDataQuery-objects your data is returned as a DataTable-object, which seems friendly and familiar. All data is however returned as string-data. While not the end of the world, it means we lose type-safety.
However our problem is something else entirely: Seemingly Sharepoint does not treat datatypes and datatype-conversions the same way as your regular .NET-functions do.
A simple example: A guid in sharepoint will get returned as upper-cased string-data in a DataTable result-set, while working with the Sharepoint object-model will yield you genuine Guid-objects. A genuine Guid-object whose the .NET default ToString-conversion will result in a lower-case string.
I have no idea how this yields for floats and what decimal delimiter will be used in the ToString-operation, or for other data-types where format rules may vary (Dates anyone?). I know however that next time I will be checking all data before running any code on it.
The morale: If you are using different data-sources for the same data. these data can only be used for presentation and not trusted for data-processing, unless properly checked, preprocessed and verified.
Once you have acquired a SPList-object, working with lists is much nicer than working with CAML-queries and resulting DataTable-objects, for obvious reasons. You get to work on hierarchical objects, with a defined structure and type.
Do however not try to delete ListItem-objects on a SPQuery result-set directly. This process will not get tagged as a deferred operation to be done when the list itself is updated. Your modification will invalidate the enumeration process and give you a InvalidOperationException.
Iterate over the list and copy the ListItem-objects you want to delete to a generic list. Then iterate over the generic list and instead delete the ListItem-objects there.
Once Sharepoint has decided that your assembly is needed, it may get stuck in the GAC and you may have to reboot your server or development environment in order to be able to deploy a new development revision.
Sometimes the assembly seemingly gets replaced, but Sharepoint or some process is still holding your code cached and no matter how many redeployments you do, your changes will have no effect.
Hints that suggests this is happening are among the following: Updates which should have 100% guaranteed visible effect doesn't (yeah, I know). One sure sign is that Visual Studio during debugging complains about source being out of sync with the assembly in GAC, when you just rebuilt and redeployed 2 nanoseconds ago.
Make sure to have as few inter-assembly references as possible to minimize this problem.
Reusing XSL Stylesheets
Before attempting this, check for any proprietary Microsoft extensions referenced in the stylesheets.
Some of the XSL Stylesheets supplied with MOSS 2007 uses .NET callback-functions embedded in the stylesheets, meaning they can only be used if called by Sharepoint-objects like the ContentQuery Web-part.
Setting up your code to reuse existing Sharepoint-resources can prove to be a dead end and a waste of time.
These are but a few examples. If I come off as a ranting developer wanting to went, there is a reason for it. Same for me having been smoking more than 20 cigarettes a day lately.
Hopefully going trough this list will help you avoid the same pitfalls and deliver Sharepoint-based development-projects with a little less pain and cursing involved.