“Oldie, but a goldie”. In this post I will describe how to configure SharePoint Lookup field programmatically. People are still asking for help on this topic a lot. Hopefully more and more developers are taking Code approach instead of XML to provision SharePoint features. I am still getting used to it since doing everything in XML is still a habit for me. In this case the approach is hybrid – the field itself is defined in XML, but the properties are set in code.

Let’s take the following Lookup field as an example:

 <Field ID="{FD47C240-961D-4AB0-9143-36172414E243}"
         Type="Lookup"
         Name="SPBB_Programme"
         StaticName="SPBB_Programme"
         DisplayName="Programme"
         Description=""
         Group="SPBB Columns"
         DisplaceOnUpgrade="TRUE"
         Required="TRUE" />

This field will reside in a list called Projects and it will allow users to select a Programme from another list. Usually you would have List and ShowField attributes set in XML. But what if you wanted the Lookup field to point to a List in different Web? There would be no way how to do it in XML.

Setting Lookup field properties by code might tricky, since one of the main properties SPFieldLookup.LookupList is Read Only. Luckily SPFieldLookup.SchemaXml is not. This is were you set List and WebId attributes of the Lookup field. I’ve got this handy function here to replace the XML attributes:

public static string ReplaceXmlAttributeValue(string xml, string attributeName, string value)
{
    if (string.IsNullOrEmpty(xml))
    {
        throw new ArgumentNullException("xml");
    }
    if (string.IsNullOrEmpty(value))
    {
        throw new ArgumentNullException("value");
    }
    int indexOfAttributeName = xml.IndexOf(attributeName, StringComparison.CurrentCultureIgnoreCase);
    if (indexOfAttributeName == -1)
    {
        xml = xml.Replace("<Field", "<Field " + attributeName + "='" + value + "'");

        return xml;
    }
    int indexOfAttibuteValueBegin = xml.IndexOf('"', indexOfAttributeName);
    int indexOfAttributeValueEnd = xml.IndexOf('"', indexOfAttibuteValueBegin + 1);
    return xml.Substring(0, indexOfAttibuteValueBegin + 1) + value + xml.Substring(indexOfAttributeValueEnd);
}

First you get both lists and the Lookup field that you want to configure:

var projectsList = web.GetList(SPUtility.ConcatUrls(web.ServerRelativeUrl, "Lists/Projects"));
var programmesLookupField = (SPFieldLookup)projectsList.Fields.GetFieldByInternalName("SPBB_Programmes");
var programmesList = web.GetList(SPUtility.ConcatUrls(web.ServerRelativeUrl, "Lists/Programmes"));

Then you replace List and WebId attributes in your field’s schema:

programmesLookupField.SchemaXml = ReplaceXmlAttributeValue(ReplaceXmlAttributeValue(programmesLookupField.SchemaXml, "List", programmesList.ID.ToString()), "WebId", web.ID.ToString());
programmesLookupField.LookupField = "Title";
programmesLookupField.Update();

And voila – you have a Lookup field pointing to a List in a different web site.

Hope this helps!