Question

I am often coming to the point that I need to create lookup fields pointing on lists which are also created in the solution.
There are many ways to do it either by using feature receiver or by using the declarative way with xml. Even in the last mentioned way I am often coming to the situation in which it does not work as expected.
Therefore my question what you see what might be the best practices to achieve it. I want to do it the declarative way due to the better maintainability of the solutions.

Some of the mentioned issues are for example that these created site fields are somehow loosing their list references, so that they are not useable in other lists.
(Exception message: <nativehr>0x80070057</nativehr><nativestack></nativestack>)

Was it helpful?

Solution 2

Maybe I was a bit too fast in asking this question.
Short after this post I found the Blog Entry: "Lookup fields as site column declarative deployed" of Stefan Bauer.
This entry was exactly what I was searching for. And after simple first testings it showed that it is working.
The secret was the following feature implementation:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPSite targetSite = properties.Feature.Parent as SPSite;

    using (SPSite site = new SPSite(targetSite.ID))
    {
        using (SPWeb web = site.OpenWeb())
        {
            SPField lookupField = web.Fields.TryGetFieldByStaticName("Colors");

            if (lookupField != null)
            {
                // Getting Schema of field
                XDocument fieldSchema = XDocument.Parse(lookupField.SchemaXml);

                // Get the root element of the field definition
                XElement root = fieldSchema.Root;

                // Check if list definition exits exists
                if (root.Attribute("List") != null)
                {
                    // Getting value of list url
                    string listurl = root.Attribute("List").Value;

                    // Get the correct folder for the list
                    SPFolder listFolder = web.GetFolder(listurl);
                    if (listFolder != null && listFolder.Exists == true)
                    {
                        // Setting the list id of the schema
                        XAttribute attrList = root.Attribute("List");
                        if (attrList != null)
                        {
                            // Replace the url wit the id
                            attrList.Value = listFolder.ParentListId.ToString();
                        }

                        // Setting the souce id of the schema
                        XAttribute attrWeb = root.Attribute("SourceID");
                        if (attrWeb != null)
                        {
                            // Replace the sourceid with the correct webid
                            attrWeb.Value = web.ID.ToString();
                        }

                        // Update field with new schema
                        lookupField.SchemaXml = fieldSchema.ToString();
                    }
                }
            }
        }
    }
}

OTHER TIPS

The first feature I did in the declarative fashion with XML, and that was the last one I did that way. It is ugly and very static in it's definition.

Every other feature afterwards that had to provision lists or libraries were all done in the feature activation code. This way was much better to develop, maintain, and upgrade.

If code is an option you're better off doing that, but if you're stuck in the sandbox, consider this:

The problem with lookup columns is that they must be deployed after the parent list is deployed, so you can't just throw them in an elements file where all your other fields are defined. Look at the package definition in your solution. The element defining your lookup must be listed after the element definging your parent list, or else the lookup will have no list to bind to when it's deployed, and will be broken.

I blogged about this a few years back with a suggested workaround to deploy your field alongside your list instance.

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top