terça-feira, 5 de junho de 2012

Deploying Custom Child Content Types declaratively VS Deploying Custom Child Content Types using object Model in Sharepoint 2007




So,  one day I was trying to deploy a child content type to MOSS inheriting from a Custom Content Type defined in the UI.

Seemed like a easy and uncomplicated task, but it wasn't, and it actually compromised my WSS content database!

Context by steps taken:

STEP 1: Using the UI I created a Custom Content Type inheriting from the Article Page, which I named

STEP 2: Using a Feature I tried to create a new content type using the previous content type as a parent.
<ContentType   ID=
"0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237
AF3900242457EFB8B24247815D688C526CD44D009E1CF1269B1F4F4E940C8F13F7D544DD01"
         Name="FilhoDeclarativo" Group="Tipos de Conteúdo Personalizados" 
Version="1">
        <Folder TargetName="_cts/FilhoDeclarativo" />
        <DocumentTemplate TargetName="/_layouts/CreatePage.aspx" />
        <XmlDocuments>
            <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint
/v3/contenttype/forms">
                <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint
/v3/contenttype/forms">
                    <Display>DocumentLibraryForm</Display>
                    <Edit>DocumentLibraryForm</Edit>
                    <New>DocumentLibraryForm</New>
                </FormTemplates>
            </XmlDocument>
        </XmlDocuments>
    </ContentType>
 
 
 
You can notice the 01 in bold on the content type ID.
Although this feature activated properly the content type didn't
show on the UI.
And when I tried to create a new child content type using the UI 
I kept getting:


This happens because the column NextChildByte of the table dbo.ContentType 
in the WSS_contentDatabase still has a value of "1". 






















http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/5e30ade2-93b0-4f5c-8acd-25b73946500c/
 
 
This situation could be corrected by updating this value 1 to a value of 2 using 
a SQL comand, but this is not advisable since microsoft doesn't support this. 
 
 
So I decided to try to create a child content type using the Object Model.

  public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
      SPSite siteCurrent = (SPSite)properties.Feature.Parent;

      SPSecurity.RunWithElevatedPrivileges(() =>
        {


          using (SPSite site = new SPSite(siteCurrent.RootWeb.Url))
          {
            bool original = site.AllowUnsafeUpdates;
            site.AllowUnsafeUpdates = true;

            using (SPWeb objWeb = site.OpenWeb())
            {

              bool originalobjWeb = objWeb.AllowUnsafeUpdates;
              objWeb.AllowUnsafeUpdates = true;


              createContentType(
                @"0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB0
64584E219954237AF3900242457EFB8B24247815D688C526CD44D009E1CF1269B1F4F4E9
40C8F13F7D544DD", "FilhoProgramado", site);



              objWeb.AllowUnsafeUpdates = originalobjWeb;

            }

            site.AllowUnsafeUpdates = original;

          }




        });
    }
 
 
 
 
   public static SPContentType createContentType(string parentCtypeID,
 string contentTypeName, SPSite site) 
    {      
      
      SPContentTypeId parentID = new SPContentTypeId(parentCtypeID);
      SPContentType cTypeParent = site.RootWeb.AvailableContentTypes[parentID];

      SPContentType custom = new SPContentType(cTypeParent, 
site.RootWeb.ContentTypes, contentTypeName);
      site.RootWeb.ContentTypes.Add(custom);
      custom.Update();
      site.RootWeb.Update();
      
      return custom ;   
    
    }
 
 
So by using the Object Model it's possible to inherit from a 
Custom Content type defined in the UI, most probably because you don't define 
the ChildByte yourself.

  
 
 Cheers!