SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

SharePoint Programmatically: Provisioning Lookup Fields

Provisioning Content Type’s fields is quite straight forward when using Solutions: using Element Manifests you can define your own Content Types and their properties among which fields. Unfortunately there is one serious con to the solution Microsoft has offered: you simply cannot provision any Lookup Field using the Element Manifest.

Lookup Fields obtain their values from an existing list. Each Lookup Field is being linked to its list using the list’s ID. As the ID’s are being generated after creating the instances there is no way to provision a Lookup Field linked to a newly created list during Solution deployment. That’s when Feature Receivers are useful. Feature Receivers are nothing more than custom code you can attach to events triggered by a feature. Provisioning a custom field programmatically works exactly the same as doing it using the GUI: first you need to create a Site Column and then you need to attach it to the Content Type of your choice.

Assuming you have a solution with a feature called ContentDefinition responsible for deploying List Templates, provisioning List Instances and creating Site Columns and Content Types. It would look something close to:

<Feature Id="GUID"
              Title="Content Definition"
              Description="Configures content definition"
              Version="1.0.0.0"
              Scope="Site"
              Hidden="FALSE"
              xmlns="http://schemas.microsoft.com/sharepoint/">
       <ElementManifests>
              <ElementManifest Location="SiteColumns\SiteColumns.xml"/>
              <ElementManifest Location="ContentTypes\ContentTypes.xml"/>
 
              <!-- Lists -->
 
              <!-- Custom List -->
              <ElementFile Location="CustomList\schema.xml"/>
              <ElementFile Location="CustomList\AllItems.aspx"/>
              <ElementFile Location="CustomList\DispForm.aspx"/>
              <ElementFile Location="CustomList\EditForm.aspx"/>
              <ElementFile Location="CustomList\NewForm.aspx"/>
              <ElementManifest Location="CustomList\Elements.xml"/>
       </ElementManifests>
</Feature>

First of all you provision your Site Columns and Content Types. Then you deploy a custom List Definition and using Elements.xml you create a new instance of that list.

To make use of Feature Receivers you need to extend the Feature element with two attributes: ReceiverClass en ReceiverAssembly:

<Feature Id="GUID"
              Title="Content Definition"
              Description="Configures content definition"
              Version="1.0.0.0"
              Scope="Site"
              Hidden="FALSE"
              xmlns="http://schemas.microsoft.com/sharepoint/"

              ReceiverAssembly="Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=keytoken"
              ReceiverClass="Assembly.ContentDefinitionFeatureReceiver">

Now you can proceed to create the ContentDefinitionFeatureReceiver class. First of all inherit from the Microsoft.SharePoint.SPFeatureReceiver class. Then override the event you want to use: as for Fields provisioning you should use the FeatureActivated synchronous event.

As I have already mentioned you need to complete two steps in order to provision a Lookup Field: you have to create a new Site Column and then add it to the desired Content Type. The best approach is to create separate methods to complete both tasks as you might need to provision multiple Lookup Fields.

public static SPFieldLookup CreateLookupField(string fieldName, string group, bool required, bool allowMultipleValues, SPWeb w, SPList lookupList, string lookupField)
{
       w.Fields.AddLookup(fieldName, lookupList.ID, lookupList.ParentWeb.ID, required);
       SPFieldLookup lookup = (SPFieldLookup)w.Fields[fieldName];
       lookup.AllowMultipleValues = allowMultipleValues;
       lookup.LookupField = lookupField;
       lookup.Group = group;
       lookup.Update(true);
       return lookup;
}

You can use this method like this:

SPFieldLookup lookup = CreateLookupField("CustomLookup", "Custom fields", false, false, SPContext.Current.Site.RootWeb, SPContext.Current.Site.AllWebs["MyWeb"].Lists["CustomList"], "Title");

The next step is to link the created Lookup Field to the existing Content Type:

public static void LinkFieldToContentType(SPWeb web, string contentType, SPField field)
{
       SPContentType ct = web.ContentTypes[contentType];
       ct.FieldLinks.Add(new SPFieldLink(field));
       ct.Update();
}

As we have just created a method returning the created Lookup Field all we have to do is to call the LinkFieldToContentType method with the created field passed as parameter:

LinkFieldToContentType(SPContext.Current.Site.RootWeb, "MyContentType", (SPField)lookup);

It is important you pass the root web as the web parameter: it’s the web containing the definitions of your Content Types.

And that’s all. As both of the methods are static you could incorporate them in a Utility class and make use of them in any of your receiver classes.


Posted 09-06-2007 1:00 AM by Waldek Mastykarz

Comments

Links (9/6/2007) « Steve Pietrek’s SharePoint Stuff wrote Links (9/6/2007) &laquo; Steve Pietrek&#8217;s SharePoint Stuff
on 09-06-2007 7:29 PM

Pingback from  Links (9/6/2007) &laquo; Steve Pietrek&#8217;s SharePoint Stuff

Driebier.net wrote Strong-typed provisioning of custom lists in Sharepoint 2007
on 10-13-2007 7:08 AM

Strong-typed provisioning of custom lists in Sharepoint 2007

Antoine Pichot wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 11-23-2007 2:35 PM

Great Job Waldek,

I've also discussed about an association between a lookup field a a list, via a feature.

If you please, you can go there

apichot.blogspot.com/.../sharepoint-2007-create-field-lookup-and.html

Manas R Moharana wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 01-11-2008 2:32 AM

it was a greate post. and it is working perfectly but one problem is when we select multiple value from lookup field the result  always defferent .mean some time it take 2 value some time it is taking 3 .and it is taking value on its own.

plz tell me why it is happning . and can we do it by using  xml file.

ok

thanks once again for this post.

can

Manas R Moharana wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 01-11-2008 2:37 AM

in the preveous comment  ,bymistake i have specify wrong mail id.as ( mmoharana@leveernt.com)

thecorrect one is mmoharana@leverent.com

TimR wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 04-18-2008 6:22 PM

On www.it-dev.pl/.../SharePoint_DSL_ToolKit.aspx there is a DSL addin to Visual Studio to model CAML schema including lookups, but there is little information except screencast. I asked about demo and I'm waiting.

Creating Lookup Columns Using Features in SharePoint 2007 « Rusty’s SharePoint Blog wrote Creating Lookup Columns Using Features in SharePoint 2007 &laquo; Rusty&#8217;s SharePoint Blog
on 07-08-2008 7:08 PM

Pingback from  Creating Lookup Columns Using Features in SharePoint 2007 &laquo; Rusty&#8217;s SharePoint Blog

david wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 08-31-2008 8:57 AM

you can also look at infowise product - Infowise Connected Fields - its also a manipulation of MOSS lookup fields

www.infowise.co.il/Product_ConnectedFields_2007.aspx

Test wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 03-18-2009 7:22 AM

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Security;

using Microsoft.SharePoint;

[assembly: AllowPartiallyTrustedCallers]

namespace TestClassLibrary

{

public class HelloWorldWebPart : WebPart

   {

       protected override void Render(HtmlTextWriter writer)

       {

           currentWeb.AllowUnsafeUpdates = true;

           SPWeb currentWeb = SPContext.Current.Web;

           SPList list = currentWeb.Lists[VivekList];

           SPListItem newListItem = list.Items.Add();

           newListItem["Title"] = "Root";

           newListItem["City"] = "Root";

           newListItem.Update();

       }

   }

}

by this you can access list in sharepoint and insert items in that ..this is very usefull article.. i have't founde this on net so i am posting this..but this will insert item when list will be there. so first need to create a list with two column title and city...and then through C# prgm u can add items programtically

Enjoy Sharepoint!

Manuel wrote re: SharePoint Programmatically: Provisioning Lookup Fields
on 04-24-2009 2:03 PM

Hi Waldek,

I am trying your approach but I am having some problems.

First of all, when I am creating a site from the site definition wich includes this feature, SPContext.Current is null.

I think I have overcome this problem using properties.Feature.Parent to get de Web instead.

Second, once I get the web being created, the list collection doesn't have the list that I have to reference in my lookup field. (I guess because my code gets called before the list is created in the feature).

What should I do? I don't understand why in your scenario you dont have the same problem.

Thank you,

Manuel

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.