Declaratively provisioning a lookup column

In SharePoint development, developers are often stymied be seemingly simple tasks. Provisioning a lookup field using the declarative model in a solution package is one such task. The most common symptom of an improperly-provisioned lookup is that no error will occur on deployment, but the lookup field will have an empty reference to its parent list when viewed in List Settings. Developers will usually, and correctly, assume that the field is broken because the parent list did not exist yet when the field is provisioned. The most common way I have seen developers address this is to use a Feature Receiver to provision their lookups after declaratively provisioning everything else because they cannot figure out a way to make the declarative approach work.

Today on Stack Exchange I saw another question on this topic, and I felt compelled to write this post to clarify the issue.

The trick to doing this right is understanding that the order in which the package deploys the artifacts is important. Look at the image below, which shows a fairly representative simple data model for a SharePoint solution. The screen shot is from VS2102/SP2013, but it works exactly the same in 2010.

package

It shows fields, content types, and lists, deployed in that order. Now, the Projects list has a lookup to the Clients list. If I put that lookup in the SiteColumns element, it will fail, because it will have been provisioned in the wrong order. The practice I have developed to make this work is to put the Field element for the lookup directly under the ListInstance element it depends on. By doing this there is no possibility the lookup will be provisioned out of order, because SharePoint will deploy the stuff in an individual elements file in the order it appears in the file:

elements

Now, when I provision my related lists, everything is properly hooked up, and I didn’t have to write any code to do it.

…and by the way, I discovered this trick by taking a saved site template and opening it up using the “Import a Solution Package” project type in Visual Studio 2010 (you can learn a LOT about SharePoint’s provisioning process by doing this, by the way). And this approach works exactly the same in 2010 and 2013 (and, I would suspect, in 2007 as well).