Tip for lessening the SharePoint pains

An ex-colleague used to say that SharePoint = Share the pains, and he’s mostly right 😀 – particularly around rapid development, debugging and testing. 

I have found one particular approach that can greatly lessened those pains, and that is to move as much code into a business layer, and make as little “contact” with the SharePoint platform as possible until the end of the dev cycle.

As an example, let say you were developing a feature that when activated will change the title of a list. This feature will require a feature receiver. You could write a class that inherits from SPFeatureReceiver, and in this class do what you have to do:

public class ChangeListTitleFeatureReceiver : SPFeatureReceiver
{
        public override void FeatureActivating(SPFeatureReceiverProperties properties)
        {
            //Get list
            //Change list title
        }
}

This class would then be referenced in your feature XML as the receiver.

Consider the pains here:

  • Hard to isolate problems – You are mixing both XML and code. If something goes wrong, is the problem in your code? or the XML? or the SharePoint instance you are deploying to?
  • Development is painfully slow and tedious:
        • Assembly needs to be re-GACed and app pool needs to be recycled if you want to see the effect of a code change – this will cost you at least 20 seconds each time.
        • You need to attach to process to debug.
        • Hard to repeat code/compile/run cycles for testing and debugging – because you have to restore SharePoint to a good state prior to each run, in this case it would involve deactivating feature + reactivating feature.

A better approach is to move the logic into a business layer, e.g. the ListTitleUpdater class:

public class ListTitleUpdater
{
        public void ChangeTitleForList(SPList list)
        {
        }
}

The responsibility of this class is to update the title of a given list. It does not need to know whether this is being done as part of a feature receiver or a button click on a page.

The idea is then you would develop and test this class in isolation, free of the SharePoint platform, using a console harness application. Only when you are completely satisfied/confident with it, you would then wire the feature receiver class to the feature through XML and invoke this class from the feature receiver class:

public class ChangeListTitleFeatureReceiver : SPFeatureReceiver
{
        public override void FeatureActivating(SPFeatureReceiverProperties properties)
        {
            //Get list
            new ListTitleUpdater().ChangeTitleForList(list);
        }
}

What is the benefit of this approach?

  • Isolation of problems – you can largely eliminate XML and the SharePoint deployment infrastructure as the cause of any peculiar problem.
  • Quick and painless code/compile/run cycles – as you have removed the SharePoint infrastructure, you do not need to re-GAC or recycle the app pool. You also do not need to deactivate + reactivate feature. The console app will also launch much quicker than your SharePoint instance.
  • Easy to debug – no longer need to attach to process.

Other benefits:

  • Encourage better design and architecture – this is a layered architecture approach. The business logic will be more reusable and better protected from requirement changes.
  • More testable – because the business logic resides in a separate class, it is much easier to write unit tests for. For example, you can instantiate it and mock the list parameter easily.

Yes, you cannot avoid XML and will have to make contact with the SharePoint infrastructure eventually. The point is though, this can be very later on in the dev cycle, and 90% of the complex logic will be developed and tested in a stand-alone class.

Yes, Visual Studio 2010 makes the F5 debug/run experience a little nicer, but it will not be as fast as doing so from a console harness program.

Posted in SharePoint | Leave a comment

Catching SPWeb created (provisioned) event

In 2010 the SPWebEventReceiver class has a WebProvisioned method which you could override. There is no such thing in 2007 (doh!!).

One way to get around this is to use the method described here: http://sharepointmagazine.net/technical/development/introduction-to-sharepoint-feature-stapling-part-2, which essentially involves creating another thread and monitor the SPWeb.Provisioned attribute.

However, it is worthwhile to note that this may not work if the site was created through stsadm, as “the tool may exit before the extra thread gets executed” (http://social.msdn.microsoft.com/Forums/en/sharepointdevelopment/thread/77f239f9-64a9-4393-9ec7-c0b08b55c7f4).

Posted in SharePoint | Leave a comment

Can’t change Display Name (or Title property) of Title field during site provisioning

We have a requirement to change the Display Name (i.e. the Title property) of the Title field of a custom list during site provisioning.

The code to do this is simple, but some for reason it would just not work. There are no exceptions but the change won’t stick. If we take the same code, and apply it to some other fields, then it works for that field. This suggests that there are something special about the Title column.

Here are the methods that we have tried:

  1. Use feature receiver code
  2. Use site provisioning code
  3. Change the list definition schema
  4. Use feature stapling

The strange thing is the 1st option works when the feature is deactivated and reactivated after the site has been created, but does not work during site provisioning.

This hints that this particular change must be applied after the site has been created.

Unfortunately there are no WebProvisioned event in 2007 (but there is in 2010!!!). One way to get around this is to use the method described here: http://sharepointmagazine.net/technical/development/introduction-to-sharepoint-feature-stapling-part-2, which essentially involves creating another thread and monitor the SPWeb.Provisioned attribute.

We found that using this method works! We were able to change the Title property of the Title field during site creation. (Hoorray!! took us nearly a week of investigation).

However, it is worthwhile to note that this may not work if the site was created through stsadm, as “the tool may exit before the extra thread gets executed” (http://social.msdn.microsoft.com/Forums/en/sharepointdevelopment/thread/77f239f9-64a9-4393-9ec7-c0b08b55c7f4).

I stress that this convoluted approach is necessary only for updating the Title column. Other columns work perfectly through the normal Provision method of the SPWebProvisioningProvider class.

Posted in SharePoint | Leave a comment

WSPBuilder config settings

There are many settings you can tweak with WSPBuilder. Type wspbuilder -help at the command prompt to get a complete list of them.

You can set these settings via the command line args, or a config file. To use a config file, create a WSPBuilder.exe.config file at the root of your project and add the settings to the appSettings section of the config file.

One of the settings that could be useful for debugging is TraceLevel. There are 5 levels as follow:

“0” gives no messages
“1” gives error messages
“2” gives errors and warnings
“3” gives information
“4” gives verbose information

The default value is 3.

These traces are written to the ULS. Use a tool like ULS Viewer (http://code.msdn.microsoft.com/ULSViewer) to monitor them.

Posted in SharePoint, WSPBuilder | Leave a comment

How did Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll ended up being in the SafeControl list??

In SharePoint, The SafeControl list is defined in the web.config and is a white list of controls that can be placed onto a SharePoint page.

The other day I was packaging my solution using WSPBuilder, deploying the WSP, and found that somehow the EntLib ExceptionHandling DLL was being added to the SafeControl list by the deployment. This was causing errors for my site. The ExceptionHandling DLL is being referenced by my project, but was not intended to be added to the SafeControl list.

I looked closer at the output window in Visual Studio and noticed this message from WSPBuilder:

———–
Adding assembly: Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll
Could not resolve: Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35. Please define the -DLLReferencePath with the path to the referenced assemblies. However a SafeControl tag for the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.Unity.ExceptionHandlingBlockExtension class has been created.

SafeControls added: 1
———–

So WSPBuilder added the EntLib DLL to the SafeControl automatically. But why?

The class ExceptionHandlingBlockExtension inherits from a base class in the Unity DLL. My reason is that because WSPBuilder could not locate the Unity DLL, it could not work out whether the ExceptionHandlingBlockExtension SHOULD be in the SafeControl list (e.g. is it inheriting from a Control class?), and hence it went ahead and add it to the list anyway.

The other interesting thing is even if I include the Unity DLL in the WSP (i.e. I do this by ensuring that the Unity DLL is copied to the project’s bin folder before running WSPBuilder), WSPBuilder still cannot locate the DLL.

I have found that WSPBuilder will only locate the DLL if the DLL is in the GAC, or if the DLLReferencePath setting is used.

To use the DLLReferencePath, one way would be to create a WSPBuilder.exe.config file at the root of your project and then specify the DLLReferencePath as a key in the appSettings section.

Posted in Enterprise Library, SharePoint, WSPBuilder | Leave a comment

Cannot connect to TFS: TF31002 and TF30331

Symptom: Cannot connect to TFS and the following error messages appear:

TF31002: Unable to connect to this Team Foundation Server: http://tfs.global.yourServer.name:8080/tfs.
Team Foundation Server Url: http://tfs.global.yourServer.name:8080/tfs.

Possible reasons for failure include:
– The name, port number, or protocol for the Team Foundation Server is incorrect.
– The Team Foundation Server is offline.
– The password has expired or is incorrect.

Technical information (for administrator):
The remote server returned an error: (503) Server Unavailable.

OR

TF30331: Team Explorer could not connect to the Team Foundation server http://tfs.global.yourServer.name:8080/tfs used during your last session. The server may be offline or the network is unavailable. Contact your Team Foundation Server administrator to confirm that the server is available on the network. Use the Connect to Team Foundation Server command on the Tools menu to reconnect to your previous server.

The server returned the following error: The request failed with HTTP status 503: Service Unavailable.

Cause and solution:

One thing that could cause these errors is the proxy setting on the client machine. Remember that the proxy setting that you set in IE will apply to the whole machine, and will affect other apps on that machine. As far as I know, some additional configurations are needed to get TFS to work with a proxy.

If you are getting the above errors, it is worthwile try turning off the proxy on your machine to see if that’d work and hence isolate the problem. To turn off proxy, go to IE, then Internet Options, then Connections tab, then LAN settings, then clear the “Use a proxy server checkbox“, also try clearing the “Automatically detect settings” checkbox.

Posted in TFS | 4 Comments

Querying a Hyperlink field using CAML

Recently I had a requirement to search for items with a certain URL in the Hyperlink field.

I noticed that the value being stored in the Hyperlink field is of the format ,. The is an absolute URL.

Using a CAML query that searches for a matching absolute URL returns no result. It turns out that I have to drop the ‘http://serverName’ from my query. So if the URL I wanted to search on was ‘http://myServer/mySite/lists/…’, then I would just search on ‘/mySite/lists/…’ in the CAML, and I would still use the Eq operator.

Here ‘myServer’ is the name of my current SharePoint server. It would be interesting to see what would happen if myServer was a DNS to some other non-SharePoint website.

Posted in CAML, SharePoint | Leave a comment

New CAML operator in SharePoint 2010: IN

It took me 20 mins to work out why my CAML was working against 1 environment and not another.

It turns out because I was using the IN operator and that’s new in 2010 and not available in 2007.

This new operator is a god-sent, because no longer will you have to do multiple nested OR clauses.

Here is the link to MSDN for this operator: http://msdn.microsoft.com/en-us/library/ff625761.aspx.

Posted in CAML, SharePoint | 2 Comments

CAML Gt AND Lt AND calculated field AND the wicked U2U CAML Query Builder

U2U CAML Query Builder is a must have tool for SharePoint developers, but today it was giving me grief.

I have a calculated column called ‘Duration (months)’. I wanted to find items where duration is less than 24 and more than 6.

I used U2U to generate the query using LT and GT but it was returning no items. The weird thing is when I removed the AND (i.e. single condition) or replace the AND with OR, then it was returning items.

It turns out that it was because U2U was putting ‘Calculated’ as the Value Type. When I changed the type to ‘Number’ (i.e. the OutputType of the calculated field) then everything works!

Posted in CAML, SharePoint, SPFieldCalculated | Leave a comment

Constructor on type ‘Microsoft.SharePoint.SPFieldCalculated’ not found – and the weird SharePoint API

Observed in: SharePoint 2007 and SharePoint 2010.

Today I was writing some code to add an SPFieldCalculated column to a list. I got the error message

Constructor on type ‘Microsoft.SharePoint.SPFieldCalculated’ not found.

when calling

SPFieldCollection.CreateNewField(fieldType.ToString(), displayName)

This call was working fine for other field types.

It turns out that the method I should be using is

SPFieldCollection.Add(String displayName, SPFieldType fieldType, Boolean isRequired)

The Add method is better than the CreateNewField method because

  1. It works with SPFieldCalculated 🙂
  2. The new field seems to be automatically added to the collection (as is noted in MSDN doco), whereas CreateNewField does not add the field to the collection, you have to make a separate call to add.
  3. You can pass the strongly-typed SPFieldType enum (as oppose to passing a string value to identify the field type).

Note that the Add method returns the internal name of the newly created field. At times you will want to get this field back out from the collection to do further processing. To do this, you should use the SPFieldCollection.GetFieldByInternalName(internalName) method (as oppose to SPFieldCollection[fieldName] because the latter is an indexer using display name).

Posted in SharePoint, SPFieldCalculated | Leave a comment