0

I'm trying to develop a document set content type for SharePoint 2013 on premise using Visual Studio. I found a very handy link to do this (http://msdn.microsoft.com/en-us/library/gg581064(v=office.14).aspx) but it does not work.

I used the code that is mentioned in the article, and everything works (the document set content type is created with the document set columns) except the Shared columns, Allowed content types and Welcome page fields. They don't update at all.

Is this still supported in SharePoint 2013 or is there something else that can cause this issue?

I included the content type in my feature so everything should work but it don't.

If you need any more information, don't hesitate to let me know.

  • Have you set Inherite to FALSE on the content type? – Robert Lindgren Mar 31 '14 at 8:19
  • Yes I did. I set Inherits="FALSE", ReadOnly="FALSE", Overwrite="TRUE" on the document set content type. On the used content type inside the document set inherits is set to True. But I think this don't need to be FALSE i guess. – deefken Mar 31 '14 at 8:24
0

I found my answer here: http://morefunthanapokeintheeye.blogspot.be/2012/10/how-to-successfully-provision-and.html

Everything in your XML content type structure can be the same (definition of welcome pages, shared content types, shared fields,...) the only extra thing that you need to add is the following feature activated/deactivated:

using System;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using System.Collections.Generic;
using Microsoft.SharePoint.Administration;
using System.Globalization;
using System.IO;

namespace My.ContentTypes.Features.MyCTypeDefinitions
{
    [Guid("a4cc1ae2-d1c6-4e7a-bef2-da1c26a0c96f")]
    public class MyCTypeDefinitionsEventReceiver : SPFeatureReceiver
    {
        // the id of the description field, so we can set it to HIDDEN later
        protected readonly String _docSetDescFieldID = "CBB92DA4-FD46-4C7D-AF6C-3128C2A5576E";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            using (SPSite site = properties.Feature.Parent as SPSite)
            {
                // pull all the content type definitions from our elements.xml
                // files as XElements, and put them in a list
                List<XElement> cTypeDefElements =
                    properties.Definition.GetElementDefinitions(CultureInfo.GetCultureInfo((int)site.RootWeb.Language)).Cast<SPElementDefinition>()
                    .Select(def => XElement.Parse(def.XmlDefinition.OuterXml))
                    .Where(ctdefel => ctdefel.Name.LocalName == "ContentType" && ctdefel.Attribute("ID").Value.Contains("0x0120D520"))
                    .ToList();

                // iterate through all my content type definitions
                foreach (XElement myCTypeDef in cTypeDefElements)
                {
                    // apply my XML docs to the definition on the site
                    CopyXMLDocsToSite(myCTypeDef, site);
                }

                site.RootWeb.Update();
            }
        }

        private void CopyXMLDocsToSite(XElement myCTypeDef, SPSite site)
        {
            // get all the XmlDocuments from my custom content type definition
            List<XElement> myXmlDocs = myCTypeDef.Descendants().Where(doc => doc.Parent.Name.LocalName == "XmlDocument").ToList();

            // get the actual content type from the site
            SPContentTypeId cTypeID = new SPContentTypeId(myCTypeDef.Attribute("ID").Value.ToString());
            SPContentType installedCType = site.RootWeb.ContentTypes[cTypeID];

            // get the existing XmlDocuments in the installed definition on the site
            // as XElements, and add them to a list
            List<XElement> installedDocs = installedCType.XmlDocuments.Cast<string>().Select(elem => XElement.Parse(elem)).ToList();

            // iterate through the ones we are customizing and add them
            foreach (XElement docToAdd in myXmlDocs)
            {
                // find the doc we want to replace
                XElement docToDelete = installedDocs.Find(doc => doc.Name.LocalName.Equals(docToAdd.Name.LocalName));

                // if there is one, delete it from the collection
                if (docToDelete != null)
                    installedCType.XmlDocuments.Delete(docToDelete.Name.NamespaceName);

                // if it is the receivers, insert ours into the existing "Receivers" doc
                // so we keep the default, inherited ones as well
                if (docToAdd.Name.LocalName == "Receivers" && docToDelete != null)
                {
                    AddNodesIntoExistingXElement(docToAdd, docToDelete, "Receiver");
                    SaveXElementAsXMLDocument(docToDelete, installedCType);
                }
                else
                {
                    // otherwise, just clean our definition and add it
                    CleanXElement(docToAdd);
                    SaveXElementAsXMLDocument(docToAdd, installedCType);
                }
            }

            // while we have a reference to the content type definition from the site,
            // change any other default field settings
            ChangeInheritedFieldSettings(installedCType);

            // write the changes into the database
            installedCType.Update(true);
        }

        private void AddNodesIntoExistingXElement(XElement xElementToAdd, XElement existingXElement, string nodeName)
        {
            // extract the nodes
            List<XElement> nodesToAdd = xElementToAdd.Descendants().Where(node => node.Name.LocalName == nodeName).ToList();

            // add into existing xdoc
            foreach (XElement node in nodesToAdd)
            {
                existingXElement.Add(node);
            }
        }

        private void CleanXElement(XElement xElement)
        {
            // check for attributes
            List<XAttribute> atts = null;
            if (xElement.HasAttributes)
                atts = xElement.Attributes().ToList();

            // replace the guts of the XElement using descendants
            // so we get rid of comments and only keep useful XML
            xElement.ReplaceAll(xElement.Descendants());

            // re-add the attributes if there are any
            if (atts != null)
                xElement.ReplaceAttributes(atts);
        }

        private void SaveXElementAsXMLDocument(XElement xElement, SPContentType installedCType)
        {
            // turn the XElement into an XmlDocument
            XmlDocument newDoc = new XmlDocument();
            newDoc.Load(xElement.CreateReader());

            // add it back to the content type definition on the site
            installedCType.XmlDocuments.Add(newDoc);
        }

        private void ChangeInheritedFieldSettings(SPContentType installedCType)
        {
            // get the installed content type definition schema
            // so we can access the default fields that were
            // inherited from the parent content type
            XElement cTypeSchema = XElement.Parse(installedCType.SchemaXmlWithResourceTokens);

            // set the "Document Set Description" field to be Hidden
            cTypeSchema.Descendants().Single(node => node.Name.LocalName == "FieldRef" && node.Attribute("ID")
                                     .Value.ToUpper().Contains(_docSetDescFieldID.ToUpper()))
                                     .SetAttributeValue("Hidden", "TRUE");

            /*
             *  make any other changes to inherited fields here
             */

            // save the edited schema back into the site
            installedCType.SchemaXmlWithResourceTokens = cTypeSchema.ToString(SaveOptions.DisableFormatting);
        }
    }
}

Doing this, the featurer will automatically copy your XML file to the right place and your content type will use this XML, instead of inherit this from the parent.

So this solved my issue. Again special thanks to Dylan Cristy.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.