Since I’m fairly new to SharePoint, I tend to use the Visual Studio extensions for Window SharePoint Services (VSeWSS) far more often than the experienced pros out there. I haven’t figured out yet why doing things by hand is better but maybe someday I will. :)
This blog will show you how to create two lists in SharePoint using VSeWSS with one list performing a lookup on the other list.
Summary of the basic steps we will follow:
1. Create a blank site definition.
2. Adding two Content Types to that definition.
3. Add a Lookup field in one of the Content Types.
4. Create two List Definitions from those Content Types.
5. Create two instances of those lists.
6. Dynamically set the correct GUID for the lookup list.
Step 1 – In Visual Studio, create a Blank Site Definition.
Step 2 – After the project is created. Add a Content Type to the project. I like to keep my folders somewhat organized so I’ll create a ContentTypes folder first.
A. Right Click Project->Add->New Folder
Name the folder ContentTypes
B. Right Click ContentTypes folder->Add->New Item->SharePoint->Content Type
Enter a name for your content and select Add. In my example, my content type will be called SimpleContentType. (yeah, I know, I’m creative. What can I say).
For the Base Content Type dialog select “Item” and then OK.
Step 3 – Now lets add a field to our content type. Since our content type base is Item it will already come with a Title field. Let’s add a description field. Open up the content type xml file that was created by Visual Studio.
In the <FieldsRefs> node add the following:
<FieldRefs><FieldRef ID="{0846A0E4-29AE-456f-AAF6-A620F214D720}" Name="Description" /></FieldRefs>
Within the <Elements> node add the following item for the Description field:
<Field ID="{0846A0E4-29AE-456f-AAF6-A620F214D720}"Type="Note"DisplayName="Description"Description="The details, nothing but the details."Required="FALSE"NumLines="6"RichText="TRUE"RichTextMode="Compatible"Sortable="FALSE"StaticName="Description"Name="Description"ColName="ntext2"RowOrdinal="0"/>
Step 4 – Add the List Definition. As before with the Content Types, let’s create a folder to hold our list definitions and keep everything nice and neat.
A. Right Click Project->Add->New Folder
Name the folder ListDefinitions
B. Right Click the ListDefinitions folder->Add->New Item->SharePoint->List Definitions from Content Type
Select the content type you created in Step 3. And check the option “Create an instance of this list”.
A new folder should be created with 4 aspx files (AllItems, DispForm, EditForm and NewForm) and 3 xml files (instance, ListDefinition and schema).
Step 5 – Change the name of the list instance.
I don’t particularly like the default list instance name that is provided. It will be the name of your list definition with the word instance tacked on. Open the file instance.xml and modify the Title attribute of the ListInstance node to something you would like better.
<ListInstance FeatureId="1678e00c-3bb4-427d-a9fb-005bbe6b5859"Title="SimpleList"Url="Lists/SimpleListDefinition"></ListInstance>
That completes our first list. Now we will create a second list that has a lookup to the first list.
Step 6 – Add another Content Type to the project.
Right Click ContentTypes folder->Add->New Item->SharePoint->Content Type
Enter a name for your content and select Add. In my example, my content type will be called MainContentType.
For the Base Content Type dialog select “Item” and then OK.
Step 7 – Now lets add the lookup field to our content type. Open up the content type xml file that was created by Visual Studio.
In the <FieldsRefs> node add the following:
<FieldRefs><FieldRef ID="{44B73528-44B7-43c6-A9E9-7434B56BED6E}" Name="SimpleField" /></FieldRefs>
Within the <Elements> node add the following item for the lookup field:
<Field ID="{44B73528-44B7-43c6-A9E9-7434B56BED6E}"Type="Lookup"DisplayName="SimpleField"Required="FALSE"List="{684FCA54-BDFD-4913-9FC9-9B7F41E8480D}"ShowField="Title"UnlimitedLengthInDocumentLibrary="FALSE"StaticName="SimpleField"Name="SimpleField"ColName="int2"RowOrdinal="0"/>
A few comments about some of the fields:
- Type – specifying lookup tells SharePoint this is a lookup field
- List – This is the GUID of the list you want to reference in the lookup. However, you won’t know the GUID of the list until the instance of the list is actually added to SharePoint. Make note of this GUID as we will use it later on this blog.
- ShowField – This is the field you want displayed in the lookup dropdown list.
Step 8 – Add the List Definition for the newly created Content Type.
Right Click the ListDefinitions folder->Add->New Item->SharePoint->List Definitions from Content Type
Select the content type you created in Step 3. And check the option “Create an instance of this list”.
A new folder should be created with 4 aspx files (AllItems, DispForm, EditForm and NewForm) and 3 xml files (instance, ListDefinition and schema).
Step 9 – As before, let’s change the name of the list instance.
Open the file instance.xml and modify the Title attribute of the ListInstance node to something you would like better.
<ListInstance FeatureId="1c2a3ac6-4f2f-49a3-963e-4d8c2c7427b6"Title="MainList"Url="Lists/MainListDefinition"></ListInstance>
Well, that completes our two lists. Now we have one last crucial step to take so that it all works out.
Step 10 – Configure the lookup list GUID at runtime.
When you created the blank Site Definition, one of the files it added was SiteProvisioning.cs. SiteProvisioning.cs can be used to hook into various events for your Site Definition. Be default, Visual Studio will add the method OnActivated that you can use to hook into when your site is being created (other methods are available to hook into).
We are going to use that event to set the correct GUID for our lookup list. Update the OnActivated method to call our method we will develop to fix the list GUID.
public void OnActivated(SPFeatureReceiverProperties properties){CorrectLookupLists(properties);}
Add the CorrectLookupLists method. This method is pretty straight-forward.
1. We get a reference to our SharePoint web and site.
2. We call the method ReplaceGuid to do the actual GUID correction
3. Some cleanup.
NOTE: The cleanup code may need to be revisited. Comments are welcomed. From my understanding you need to be sure to dispose of your web and site references. However, I believe you are not supposed to do that for the RootWeb. If so, this code will need to be updated to reflect that. Microsoft is working on a tool to help identify where you need to dispose of your SharePoint objects:
private void CorrectLookupLists(SPFeatureReceiverProperties properties){SPWeb web = null;SPSite site = null;try{if (properties.Feature.Parent is SPWeb){web = properties.Feature.Parent as SPWeb;site = web.Site;}else{site = properties.Feature.Parent as SPSite;web = site.RootWeb;}web.AllowUnsafeUpdates = true;// Fix the simple listReplaceGuid(web, "Main", "Simplelist", "SimpleField", "684FCA54-BDFD-4913-9FC9-9B7F41E8480D");}finally{if (web != null){web.Dispose();}if (site != null){site.Dispose();}}}
And finally, add the method that does the work, ReplaceGuid.
private void ReplaceGuid(SPWeb web, string mainListName, string lookupListName, string fieldName, string tempGuid){SPList lookupList = web.Lists[lookupListName];SPList mainList = web.Lists[mainListName];mainList.Fields[fieldName].SchemaXml = mainList.Fields[fieldName].SchemaXml.Replace(tempGuid, lookupList.ID.ToString());mainList.Update();}
This method is probably closer to a hack then exact because all it does is search the Xml definition for the old GUID and replaces it with the new GUID. So, technically if that GUID did show up more than once then you’ll probably do some damage. Since we are dealing with GUIDs here, I’ll take my chances. :)
We are ready to roll now. Let’s get this site deployed and see if it works.
Step 11 – Deploy your new Site Definition.
A. Set the URL to your SharePoint server: Right click project -> Properties -> Debug -> Start browser with URL.
B. Build and Deploy the web part to your SharePoint server. Right click project –> Deploy
Step 12 – Create a new site based upon your newly created Site Definition.
A. Open up your SharePoint portal in your browser.
B. Select Site Actions->Site Settings
C. Select “Sites and Workspaces” under the Site Administration section.
D. Select Create
E. Enter a Title, Description and URL.
F. Select the “Development” tab for the “Select a template” section. You should see your newly created Site Definition listed.
G. Select “Create”.
SharePoint will spin and churn for a bit and eventually it will take you to your newly created site.
Step 13 – Verify your two lists were created.
A. From the left-hand menu options “View All Site Content”, select Lists.
B. Your two list instances should show up.
c. Add a few items to SimpleList
d. And now when you add a item to MainList, you should see the SimpleField populated with the items from SimpleList.
You can download the complete source code from CodePlex:
» Similar Posts
- Adding Target Audience in SharePoint with VSeWSS
- Yes, Virginia, you can write through the BDC – Part One.
- Yes, Virginia, you can write through the BDC – Part Two.
» Trackbacks & Pingbacks
http://bilbroblog.com/trackback.ashx?id=16
» Comments
-
This is what I have been looking for! I knew there had to be a way to do this and I do not care if we call it a 'hack' or not. I have to develop in VS and this allows me to create the lookups I need. Awesome!
Daniel Walker — February 28, 2009 11:00 AM -
I downloaded the source code, but when I tried to create a site based on the template, I received this error:
Feature '06b3cbab-677a-41d2-bb75-61dbcff62785' is not installed in this farm, and can not be added to this scope.
Any idea what feature this is referring to, and how I can resolve the problem?
Thanks
Bill Saffin — May 14, 2009 12:14 AM -
Simple way to solve SharePoint complexity
Mohit — September 1, 2009 7:04 AM -
In the ReplaceGuid method, exception occur when we create new site definition. "Value is not fall within expected range. How to fix it. I did many time same as you introdure above.
Nguyen — December 1, 2009 10:19 AM -
Nguyen, make sure the values you pass to the method are correct - especially if you have renamed the list and field names.
tiff — December 4, 2009 5:40 PM