Fixing blank lookup columns in SharePoint when creating new site from a site template

One of the common issues when creating a new site from a site Template is that the lookup columns values are blanks. The full scenario is as below :
  • Create a SharePoint site
  • Add lists with lookup columns
  • Insert some data in the lists
  • Save the site as Template with its content
  • Create a new site from the Template
When you access the list which contains the lookup column, you will notice that the lookup values are empty. The lookup values still exist but they are not rendered. We have to fix the list schema by updating some properties of the lookup column. Two properties have to be updated :
  • The Web Id
  • The List Id
There are two ways to fix the list schema :
  • Using C#
  • Using Powershell
We will see how to fix the error using Powershell. The script below will let you fix the column.

$web = Get-SPWeb "Your web url"
$list = $web.Lists["Your list name"]
$column = $list.Fields["Your column name"]
$lookupList = $web.Lists["Your source list name"]
#Updating the column properties
$column.SchemaXml = $column.SchemaXml.Replace($column.LookupWebId.ToString(), $web.ID.ToString())
$column.SchemaXml = $column.SchemaXml.Replace($column.LookupList.ToString(), $lookupList.ID.ToString())
$column.Update()
write-host "Column properties have been updated"
$Web.Dispose()
  
More details about the lookup columns on MSDN.



 

How to localize site columns using resource files

Localizing SharePoint 2007 columns consist on

  •  Create resource file for each language.
  •  Add $Resources:<ResourceFilename>,<Resource key name>; to the display name of the site column.

In this article we will create a resource file BOSSContentTypes.fr-FR.resx and a BOSSContentTypes.resx .
The BOSSContentTypes.resx will contain the English labels and the other the French labels of our site columns.

This is a preview of the BOSSContentTypes.fr-FR.resx
the other file contains the same names but English values.

After creating theses two files , deploy them into the 12/Resources  folder.

Now we have to map our Display name with the values in the resource files.

this is a simple snippet from the definition of our content type.


  <Field ID="{79831820-B700-4786-AD10-69F54BED193B}" ShowInDisplayForm="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE" Type="Text" Name="Mission" DisplayName="$Resources:BOSSContentTypes,Mission;"
         StaticName="Mission" Hidden="FALSE" Required="FALSE" Sealed="FALSE" />
  <Field ID="{0F37DF23-F2AF-48ac-8EC4-126220290747}" ShowInDisplayForm="TRUE"
         ShowInNewForm="TRUE" ShowInEditForm="TRUE" Type="Text" Name="Client" DisplayName="$Resources:BOSSContentTypes,Client" StaticName="Client" Hidden="FALSE" Required="FALSE" Sealed="FALSE" />
Now just see what you have done.

How to run Code with elevated privileges

I had to create 2 calendars , first one is shared and located on the Root site and the other is personnal and located on the mySite.
The content type contains one field  AssignedTo . when the event is inserted in the Shared Calendar , it must also be add to the personal calendar of the User in the AssignedTo field.
The user who added the event has no rights on the Personal Calendar of the User in the AssignedTo field.
So the solution was to run the code with elevated privileges.

To do such a thing just user the SPSecurity.RunWithElevatedPrivilges

SPSecurity.RunWithElevatedPrivileges(delegate()
  {


you need to open the site,web and list inside the RunWithElevatedPrivileges. 


SPListItem newitem = list.Items.Add();
                                                                             newitem["ContentTypeId"] =
                                                                                 properties.ListItem["ContentTypeId"];
newitem["Title"] = properties.ListItem["Title"];
newitem["Location"] = properties.ListItem["Location"]; 
newitem["EventDate"] =properties.ListItem["EventDate"];
newitem["EndDate"] = properties.ListItem["EndDate"];  
newitem.Update();
} );


How to get the DisplayForm of an SPListItem

this is a code snippet that get the display form of an SPListItem

using (SPSite site = new SPSite("http://yoursite"))
{
    using (SPWeb web = site.OpenWeb())
    {
        SPList list = web.Lists[0];
        SPListItem item = list.Items[0];
        string diplayForm= String.Concat(item.Web.Url, "/",                   item.ParentList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url, "?id=", item.ID.ToString());
    }
}

great thx to http://www.peppedotnet.it

How to get Users Id from a UserMulti Field

If you try to get the ToString() value of a type of UserMulti field you'll get something like
"1;#Username" and for multi-user fields "1;#User1;#15;#UserX". 


It is not necessary that you create a method that parses this string to get the users ID. You can do it like that :


            SPListItem currentListItem = properties.ListItem;
            Guid guid= new Guid("A1075591-DBC7-4b9d-99F4-E03061F7716E");
            SPFieldUserValueCollection values = (SPFieldUserValueCollection)currentListItem[guid];

            foreach (SPFieldUserValue value in values)
            {

                int valueID = value.LookupId;
                string valueTitle = value.LookupValue;

            }


If you have a field of type Lookup and accepting multiple values you can use SPFieldLookupValueCollection.

Retrieve field value after ItemAdded event using its GUID

To retrieve the value of an item after the event ItemAdded , we can use the guid of the corresponding field.

 public override void ItemAdded(SPItemEventProperties properties)
        {

            SPListItem currentListItem = properties.ListItem;
            Guid guid= new Guid("A1075591-DBC7-4b9d-99F4-E03061F7716E");
            string value = currentListItem[guid].ToString();

        }

we can also use the Index of the field or the fieldname .