views:

831

answers:

1

I am trying to create a list template in SharePoint Feature using CAML. I have two content types "News" and "News Release" they both share two fields called Overview and Description.

I have been reading that the "listtemplate" caml element does not automatically add the fields from the content types, you need to specify all the fields. When fields are specified SharePoint does not update the "Used In" in the sharepoint list settings (screenshot). This is a problem as Views can't be updated with these fields.

Could this be fixed with a feature receiver written in c#?

Any ideas?

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/"&gt;
  <ListTemplate Name="News"
                DisplayName="News"
                Description="News"
                Type="100"
                BaseType="0"
                OnQuickLaunch="true"
                SecurityBits="11"
                Sequence="410"
                Image="/_layouts/images/itgen.gif"
                Unique="True"
                DisableAttachments="True" />
</Elements>

<?xml version="1.0" encoding="utf-8" ?>
<List Name="News"
      Title="News"
      FolderCreation="FALSE"
      Direction="$Resources:Direction;"
      Url="Lists/News"
      EnableContentTypes="True"
      BaseType="0" 
      Type="100"
      xmlns="http://schemas.microsoft.com/sharepoint/"
      xmlns:ows="Microsoft SharePoint">
  <MetaData>
    <ContentTypes>
      <ContentTypeRef ID="0x010007196C9EB6E5B04BAE108FD1969FD42B01" />
      <ContentTypeRef ID="0x010007196C9EB6E5B04BAE108FD1969FD42B02" />
    </ContentTypes>
    <Fields>
      <Field ID="{1E061768-0380-48e4-8E71-86CAE6DDDF30}" Type="Note" DisplayName="Overview" Name="Overviews" />
      <Field ID="{9406510E-511A-438f-AD9F-A55CED16B033}" Type="Note" DisplayName="Description" StaticName="Description" Name="Description" />
    </Fields>
    <View>
      Removed For Post
    </View>          
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>
+1  A: 

This is one of the problems having CAML do initialization for you, I always go for doing things in code if that's possible :)

I had a similar problem the other day and ended up removing the ContentTypeRef section from the list, letting it inherit just from item and in a feature receiver creating the list, adding the content types I wanted and then removing the item content type. That way the list populated correctly with the fields from the content types

Following is my feature receiver:

public void CreateList(SPFeatureReceiverProperties prop)
        {
            logger.Info("Creating list");
            using (SPWeb currentWeb = WebHelper.GetWeb(prop))
            {
                try
                {
                    SPList list = ListHelper.CreateList("Other Documents", "", "Rhb Other Documents List", true, currentWeb);
                    logger.Info("List created successfully");

                    logger.Info("Attaching content types");
                    list.ContentTypesEnabled = true;
                    list.Update();
                    list.ContentTypes.Add(currentWeb.ContentTypes["RhbOtherDocuments"]);
                    list.Update();
                    list.ContentTypes["Item"].Delete();
                    list.Update();
                    logger.Info("Content type attached");
                }
                catch (Exception e)
                {
                    logger.Error("List creation failed", e);
                    Console.WriteLine(e);
                }
            }
        }

The web helper class used in the feature receiver:

public class WebHelper
    {
        #region Helper functions
        public static SPWeb GetWeb(SPFeatureReceiverProperties prop)
        {
            using (SPSite site = prop.Feature.Parent as SPSite)
            {
                return site != null ? site.RootWeb : prop.Feature.Parent as SPWeb;
            }
        }
        #endregion  
    }

The list helper class used in the feature receiver:

public static SPList CreateList(string ListName, string description, string templateName, bool Visible,
                                        SPWeb web)
        {
            SPListTemplate template = web.Site.RootWeb.ListTemplates[templateName];
            SPList list = web.Lists[web.Lists.Add(ListName, description, template)];
            list.EnableVersioning = false;
            list.EnableAttachments = false;
            list.OnQuickLaunch = false;
            list.EnableFolderCreation = false;
            list.Update();
            return list;
        }

One thing to note is that this mechanism is probably better than via CAML because this way we don't have to maintain field information in both the content type and in the list CAML

I originally found an article (see here) that provided a big part of my solution.

armannvg