Custom Document Set content type created through code has null Welcome Page Fields in template
-
13-02-2021 - |
Question
I am creating a custom Document Set content type through server-side/C# code as follows:
SPContentType docSet = web.AvailableContentTypes["Document Set"];
SPContentType newCType = new SPContentType(docSet, web.ContentTypes, "My Custom Doc Set");
newCType = web.ContentTypes.Add(newCType);
newCType.Group = "My Content Types";
newCType.Update();
I then proceed to add some fields by creating new FieldLink
objects and adding them to the newCType.FieldLinks
collection.
I then proceed to update the WelcomePageFields
XML document in the newCType.XmlDocuments
as follows:
Dictionary<string, string> welcomPageFieldsList = new Dictionary<string, string>()
{
"Field1InternalName", "field-1-guid",
"Field2InternalName", "field-2-guid"
// etc
}
XNamespace xlmns = "http://schemas.microsoft.com/office/documentsets/welcomepagefields";
XElement welcomPageFieldsXML = new XElement(xlmns + "WelcomePageFields");
foreach (KeyValuePair<string, string> fieldInfo in welcomPageFieldsList)
{
XElement fieldElement = new XElement("WelcomePageField",
new XAttribute("Name", fieldInfo.Key),
new XAttribute("id", fieldInfo.Value)
);
welcomPageFieldsXML.Add(fieldElement);
}
List<XElement> xmlDocs = newCType.XmlDocuments.Cast<string>().Select(doc => XElement.Parse(doc)).ToList();
XElement oldXmlDoc = xmlDocs.Find(oldDoc => oldDoc.Name.LocalName == welcomPageFieldsXML.Name.LocalName);
newCType.XmlDocuments.Delete(oldXmlDoc.Name.NamespaceName);
XmlDocument newXMLDoc = new XmlDocument();
newXMLDoc.Load(welcomPageFieldsXML.CreateReader());
newCType.XmlDocuments.Add(newXMLDoc);
newCType.Update();
This all works fine, but when I try to create a new document set instance based on that content type in a document library, I get a NullReferenceException
from the Welcome Page Fields webpart on the document set homepage. I thought maybe I forgot to actually add one of the fields to the content type that I reference in the XML Documents, but no, they all match up. So I dug into the ULS logs, and I see that actually the error is thrown because some part of the process is accessing the welcome page fields from the document set template, and that's what's throwing the exception.
So I tried adding code to get the template, and add the fields to the WelcomPageFields
on the template, but that also threw a NullReferenceException
.
So I did a little digging with Powershell, got my custom content type, and then got the DocumentSetTemplate
object associated with my custom document set, and I see that the WelcomePageFields
property is apparently null
:
According to the documentation about the DocumentSetTemplate.WelcomePageFields
property, it's a read-only property, so I can't new
up a WelcomePageFieldCollection
and assign it to the template so everything gets hooked up properly.
So - how do you properly create a custom content type based on Document Set using server-side/C# code so that the WelcomePageFields
property of the template is initialized properly?
Update:
It seems like the WelcomePageFields
property on the template is an empty collection (not null
) when the content type is initially created, and it's the process of deleting the old WelcomePageFields
XML document from the content type that clears out the property on the template - even though I replace the XML document with another WelcomePageFields
XML document before I call Update()
on the content type?
Will be doing more research/experimentation, but could still use any pointers or suggestions for how to get this done...
Solution
Well, it turns out that it was indeed caused by deleting the WelcomePageFields
XML document from the content type's XmlDocuments
property. Somehow that triggers the deleting of the WelcomePageFieldCollection
on the template, making the template's WelcomePageFields
property null
, even though I had re-added a WelcomePageFields
XML document to the XmlDocuments
before I called Update()
on the content type.
But, as it turns out, if you edit/update the WelcomePageFields
on the template, it will automatically update the XmlDocuments
on the content type. So in the end all I needed to do was to add the fields I wanted to be on the Document Set homepage to the template and not touch the XmlDocuments
at all.