Wednesday, December 31, 2008

Lookup column - replace GUID of referenced list

When we create a lookup field using CAML we need to specify the name or GUID of the list from which this field gets data. Is possible that this list to be created using a feature so we will not know his GUID.
 
<Field        
ID="{DFFDD227-CC2C-4a6f-930C-44BD65CDA80F}"
Name="Location"
DisplayName="Location"
StaticName="Location"
SourceID="http://schemas.microsoft.com/sharepoint"
Group="MyGroup"
Type="Lookup"
ShowField="Title"
List="Locations"
/>





I try to specify the name of the list in field CAML definition but I do not know why after creation the field point to a strange object with a different GUID that I expected to.


The solution I found is to have a feature who can modify this GUID after the required list is created. I created a function that get the SchemaXml of the field and in this xml replace the GUID of the list. The required list and the field are send as parameters. After we have the proper SchemaXml we delete the old field and create a new one using this new schema. In the feature activation we can call this function.


Here is the code:


 



private void SetTheProperGUID(SPList catList, SPField catField)    
{
string fieldXml = catField.SchemaXml;
Regex regex = new Regex(@"List=\""(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}\""");
if (regex.IsMatch(fieldXml))
{
fieldXml = regex.Replace(fieldXml, "
List=\"" + catList.ID.ToString("B").ToLower() + "\"");
}
catField.Delete();
catList.Fields.AddFieldAsXml(fieldXml);
catList.Update();
}

4 comments:

  1. In my case when I try to get the list I receive an error. The list do not exist. But after the site is created the list is there.

    ReplyDelete
  2. Maybe the list was not yet created. In this case you can create a thread that wait that site to be provisioned.
    Add this code into FeatureActivated:
    ThreadPool.QueueUserWorkItem(new WaitCallback(DoTheJob), web.Url);

    and the function

    private void DoTheJob(object state)
    {
    string url = (string)state;
    using (SPSite site = new SPSite(url))
    {
    using (SPWeb web = site.OpenWeb())
    {
    SPList myList = null;
    while (myList == null)
    {
    Thread.Sleep(1000);
    myList = web.Lists["ListName"];

    if (myList != null)
    {
    // here your code to change GUID
    }
    }
    }
    }
    }

    ReplyDelete
  3. Small correction: If the list do not exist you will receive an error. And you also need to reinialize the web:

    SPWeb web = site.OpenWeb()
    {
    SPList myList = null;
    while (myList == null)
    {
    Thread.Sleep(1000);
    try
    {
    myList = web.Lists["ListName"];

    if (myList != null)
    {
    // here your code to change GUID
    }
    }
    catch
    {
    web = site.OpenWeb()
    }

    }
    }

    ReplyDelete
  4. if the list is from the rootweb then how can we associate it and if you have a codeset can you please share it my emailid is mnvraghuram@yahoo.com

    Thanks & Regards,
    Raghu

    ReplyDelete