Second Life of a Hungarian SharePoint Geek

May 14, 2010

Declaratively adding a lookup field to a list schema using the name of the referenced list

Filed under: CAML, SharePoint — Tags: , — Peter Holpar @ 01:09

This topic is really not a new one. I read already debates several times about if it is possible or not, see for example this post in Josh Gaffey’s blog:

Add SharePoint lookup column declaratively through CAML XML

or this post from Chris O’Brien’s blog:

Creating lookup columns as a feature

There are a lot of comments pro and cons in these posts.

Since I’ve got this question again on the MSDN forum (see create lookup column in list template without guid of parent list), I decided to check the issue myself.

In the past I deployed lists with lookup fields using the name of the referenced list formerly using a custom deployment tool, now I had to create a declarative feature using CAML definitions.

In my test I was to create a lookup field to the Title field of the standard Tasks list.

Based on the guide of Josh in the above post I first try to create a lookup site column.

To achieve this, I’ve created a simple feature that included the following fields.xml file:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  3.     <Field ID="{95d89725-eb97-428b-bc79-ee02ca8b724c}"
  4.         Name="TestField"
  5.         SourceID="http://schemas.microsoft.com/sharepoint/v3"
  6.         StaticName="TestField"
  7.         Group="Test site columns"
  8.         Type="Lookup"
  9.         DisplayName="Test field"
  10.         List="Lists/Tasks"
  11.         FieldRef="ID"
  12.         ShowField="Title" />
  13. </Elements>

The feature.xml file looks like this:

  1. <?xml version="1.0" encoding="utf-8"?>
  2.   <FeatureId="2AABD552-10B1-4561-8A19-2311D39C9A2E"
  3.           Title="List name based lookup field demo feature (site column)"
  4.           Description="The sole purpose of this feature is to demonstrate how to create list name based lookup field in WSS 3.0 using a site column"
  5.           Version="1.0.0.0"
  6.           Hidden="FALSE"
  7.           Scope="Site"
  8.           xmlns="http://schemas.microsoft.com/sharepoint/">
  9.   <ElementManifests>
  10.     <ElementManifest Location="fields.xml"/>
  11.   </ElementManifests>
  12. </Feature>

Activating the feature resulted in the following in the site columns list:

image

At first sight that was OK, but after checking the details it turned out to be not perfect:

image

As you can see on the image above, the place of the parent list was empty.

Checking the field from code showed that the LookupList property of the site column was “Lists/Tasks”, so it was not resolved to the list GUID on feature activation.

When I tried to add the site column to a list, I’ve received the following exception:

Exception from HRESULT: 0x80040E07   at Microsoft.SharePoint.Library.SPRequestInternalClass.AddField(String bstrUrl, String bstrListName, String bstrSchemaXml, Int32 grfAdd)

  at Microsoft.SharePoint.Library.SPRequest.AddField(String bstrUrl, String bstrListName, String bstrSchemaXml, Int32 grfAdd)

I’ve also tried to create a custom list definition in the same feature, but when I tried to create a new instance based on that definition, I received the following exception:

Cannot complete this action.
Please try again.   at Microsoft.SharePoint.Library.SPRequestInternalClass.CreateListFromFormPost(String bstrUrl, String& pbstrGuid, String& pbstrNextUrl)
   at Microsoft.SharePoint.Library.SPRequest.CreateListFromFormPost(String bstrUrl, String& pbstrGuid, String& pbstrNextUrl)

Although some comments suggested to remove the ShowField attribute to get it work, in my experience it did not help. It only made the case even worse, as now the column information was also empty (as one could expect logically):

image

So I have to find an alternative way. I decided to try it with a custom list definition that contains the field definition itself.

If you are new to creating custom list definitions, you can read more about that here:

How to: Create a Custom List Definition

I’ve created a feature that contains the custom list definition. The main modifications of the simple custom list schema are the followings:

  1. <ContentTypes>
  2.     <ContentTypeID="0x01"
  3.     Name="Item"
  4.     Group="Item group"
  5.     Description="Item description"
  6.     Version="0">
  7.     <FieldRefs>
  8.       <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
  9.       <!– Title –>
  10.       <FieldRef ID="{95d89725-eb97-428b-bc79-ee02ca8b7225}" Name="TestField" Required="FALSE" ShowInNewForm="TRUE" ShowInEditForm="TRUE"/>
  11.       <!– Test field –>
  12.     </FieldRefs>
  13.     <XmlDocuments>
  14.       <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
  15.         <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
  16.           <Display>ListForm</Display>
  17.           <Edit>ListForm</Edit>
  18.           <New>ListForm</New>
  19.         </FormTemplates>
  20.       </XmlDocument>
  21.     </XmlDocuments>
  22.   </ContentType>
  23.   <ContentTypeRef ID="0x0120" />
  24. </ContentTypes>
  25. <Fields>
  26.   <Field Type="Lookup"
  27.          DisplayName="Test field"
  28.          Required="FALSE"
  29.          List="Lists/Tasks"
  30.          ShowField="Title"
  31.          UnlimitedLengthInDocumentLibrary="FALSE"
  32.          ID="{95d89725-eb97-428b-bc79-ee02ca8b7225}"
  33.          SourceID="http://schemas.microsoft.com/sharepoint/v3"
  34.          StaticName="TestField"
  35.          Name="TestField" />
  36. </Fields>

and a reference for the lookup field was added to the ViewFields:

  1. <ViewFields>
  2.   <FieldRef Name="Attachments">
  3.   </FieldRef>
  4.   <FieldRef Name="LinkTitle">
  5.   </FieldRef>
  6.   <FieldRef Name="TestField">
  7.   </FieldRef>
  8. </ViewFields>

Next, I’ve installed and activated the feature:

stsadm -o installfeature -name ListNameBasedLookUp
stsadm -o activatefeature -name ListNameBasedLookUp -url http://yoursite

The custom list definition appeared on the available list types:

image

I’ve created a new instance called LookUpList1:

image

The new list instance contained the lookup field:

image

And the definition of the field was correct. It pointed to the right list (Tasks) and to the right field (Title):

image

The field was added to the default view as expected:

image

In the meantime I’ve created to item in the Tasks list:

image

When I created a new item, the values of the lookup field came from the specified source list and field:

image

And last but not least, the item is saved correctly to the list:

image

So my experience matches to Scott’s comment in Josh’s post:

“To make this method work, the field definition must exist in a list definition since the wiring up to the GUID happens when you the provision the list, rather than when you add a column to an existing content type/list.”

At the end some note:

If you want to alter the feature XML files and would like to avoid caching issues, I suggest you to alter the feature and field GUIDs each time you deploy (deactivate/uninstall/alter/install/activate/IISRESET) the feature. Ignoring this hint may cause you a lot of headache. Believe me, I tell you that from my own experience!

Another side note, that the experience may depend on the version number of SharePoint in my environment I tested it with the December 2009 Cumulative Update (12.0.0.6524).

You can find the full sample feature here.

11 Comments »

  1. […] Ich habe hier die Kurzfassung dargestellt um diese Aufgabenstellung zu lösen. Detailliertere Informationen findet ihr auch auf dem Blog von pholpar. […]

    Pingback by Deklaratives hinzufügen eines LookUp Feldes zu einer Schema.xml « Patrick von der Heydt's Blog — May 28, 2010 @ 07:23

  2. Hi,
    Great stuff!! However there is one glitch in creating lookup columns this way which is that Sharepoint 2010 throws error when we try to add an item to this list. I tried povisioning lookup column using this method of setting the “List” property in the field xml declaration.

    List is created successfully, references created correctly but it breaks on adding a dataitem to this list giving the following error

    0x80070057Invalid data has been used to update the list item. The field you are trying to update may be read only.

    Is there any workaround for this issue?

    Comment by Manish Kaushal — July 5, 2010 @ 09:50

    • Hi Manish,

      Thanks for the comment. I should point out that this post is originally for MOSS 2007/WSS 3.0, it was not tested for any version of SharePoint 2010. I will “upgrade” the solution to 2010 as my time allows that.

      Peter

      Comment by pholpar — July 5, 2010 @ 12:30

    • Reporting the exact same situation, with SharePoint 2010.

      Have you, by any chance, had a look into this already, pholpar?

      Comment by NoBody — July 16, 2010 @ 12:23

      • Sorry, not yet.

        Comment by pholpar — July 16, 2010 @ 13:55

      • Manish, NoBody,

        I’ve tested the sample feature on my SP2010 installation and it worked as expected. Double check your feature (if you altered the sample) to avoid possible typos.

        Have you created your list based on the list template included in the feature?

        Do you work with the RTM version of SP2010?

        Peter

        Comment by pholpar — July 17, 2010 @ 21:38

  3. Thanks a million! I’ve been looking all over for a way to do this and your solution worked perfectly!

    Comment by Thomas — October 8, 2010 @ 11:05

  4. Hi ,
    I have a quick question so is this lookup column getting value from the root list?

    Thanking you in anticipation

    Regards,
    raghu

    Comment by raghu — October 8, 2010 @ 13:45

  5. Hi,
    Just tried this and this list needs to be in the current web only so if we want to add a lookup column to the site and then use it in the customlist is there any work around?

    Regards,
    Raghu

    Comment by raghu — October 8, 2010 @ 14:01

  6. I’ve just tried the same for two of my lookups.

    1. A Lookup to an other list. This worked fine.
    2. A lookup to the list containing the lookup (I’ve got a list of items with a lookup giving the option to select a parent item).

    The 2nd option doesn’t work. Most likely as the list doesn’t exist when the lookup is created. I guess that the only way around this might be by creating two features for this list. 1. a feature that creates the list and then a 2nd one whcih upgrades the list with the lookup.

    Comment by pietersveenstra — December 20, 2010 @ 12:14

    • Hi Pieter,

      Yes, the list must exist before lookup is created, as SharePoint tries to resolve the list name to list GUID when the lookup field is created. I’m afraid you cannot apply this technique in a single step in scenario 2, but the plan for two separate features sound to be a viable alternative.

      Peter

      Comment by Peter Holpar — December 21, 2010 @ 21:56


RSS feed for comments on this post. TrackBack URI

Leave a reply to Peter Holpar Cancel reply

Create a free website or blog at WordPress.com.