Creating Web Template and WebProvisioned Receiver Walkthrough

Hi,

As part of my migration project from MOSS 2007 to SP2013, I realised there was a site template I had to create. Reading up on web template and site definition, I decided to go with creating web template as this is much easier.

Turns out that to get things glued up together (site columns, content types, lists, etc.) is not as straightforward as it seems as we need the right code. I have listed the final code here so if you are to go and create a new web template things will be easier (I hope) :)

It's good to read this article as well re. Web Template

Creating Site Columns and Content Types

Creating these programmatically will allow you to have more control and will be able to upgrade these in the future. So in the 'Branding' feature, I create these with the help from this article and extend the helper methods to cater for the publishing html fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public class BrandingEventReceiver : SPFeatureReceiver
    {
        public static readonly SPContentTypeId CustomCTId = new SPContentTypeId(ContentTypeId.Page.ToString() + "00C8D252303CFE4B3C9CC0A730135DBBA4");
 
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            // Retrieve the current web object (Site feature so feature Parent will be SPSite)
            SPWeb web = ((SPSite)properties.Feature.Parent).RootWeb;
 
            CreateCustomCTSiteColumnsAndContentTypes(web);
        }
 
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            // Retrieve the current web object (Site feature so feature Parent will be SPSite)
            SPSite site = (SPSite)properties.Feature.Parent;
            SPWeb web = ((SPSite)properties.Feature.Parent).RootWeb;
 
            RemoveCustomCTSiteColumnsAndContentTypes(site);
        }
 
        private void CreateCustomCTSiteColumnsAndContentTypes(SPWeb web)
        {
            //Create a new content type. Note that it inherits from item
            SPContentType CustomCT = Utility.CreateSiteContentType(web, "CustomCT", CustomCTId, "My Content Types");
 
            //Add site columns
            Utility.CreatePublishingHTMLSiteColumn(web, "customField1", "My Custom Fields");
            Utility.CreatePublishingHTMLSiteColumn(web, "customField2", "My Custom Fields");
 
            //Add the new fields to the new content type
            Utility.AddFieldToContentType(web, CustomCT.Id, "customField1");
            Utility.AddFieldToContentType(web, CustomCT.Id, "customField2");
 
            //Write the changes to the database
            web.AllowUnsafeUpdates = true;
            web.ContentTypes[CustomCT.Id].Update();
            web.AllowUnsafeUpdates = false;
        }
 
        private void RemoveCustomCTSiteColumnsAndContentTypes(SPSite site)
        {
            SPWeb web = site.RootWeb;
 
            foreach (SPWeb subsite in site.AllWebs)
            {
                if (web.Lists["Pages"] != null)
                {
                    if (web.Lists["Pages"].ContentTypes["CustomCT"] != null)
                    {
                        web.Lists["Pages"].ContentTypes["CustomCT"].Delete();
                    }
                }
            }
 
            //Delete the content type.
            //Note that if the content type is not there
            //it throws an Null Reference Exception.
            //We trap it and ignore it.
            try
            {
                var usages = SPContentTypeUsage.GetUsages(web.ContentTypes[customCTId]);
 
                if (usages.Count <= 0)
                {
                    web.ContentTypes[CustomCTId].Delete();
                    web.AllowUnsafeUpdates = true;
                    web.Update();
                    web.AllowUnsafeUpdates = false;
                }
            }
            catch (NullReferenceException)
            { }
 
            //Loop through the fields in My Custom Fields group
            //and delete them
            for (int i = 0; i < web.Fields.Count; i++)
            {
                if (web.Fields[i].Group == "My Custom Fields")
                    web.Fields[i].Delete();
            }
        }
    }

The Utility helper class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public static class Utility
{
    public static SPContentType CreateSiteContentType(SPWeb web, string contentTypeName,
        SPContentTypeId customContentTypeId, string group)
    {
        if (web.AvailableContentTypes[contentTypeName] == null)
        {
            SPContentType contentType =
                new SPContentType(customContentTypeId, web.ContentTypes, contentTypeName) { Group = @group };
            web.ContentTypes.Add(contentType);
            return contentType;
        }
        return web.ContentTypes[contentTypeName];
    }
 
    public static SPField CreateSiteColumn(SPWeb web, string displayName,
        SPFieldType fieldType, string groupDescriptor)
    {
        if (!web.Fields.ContainsField(displayName))
        {
            string fieldName = web.Fields.Add(displayName, fieldType, false);
            SPField field = web.Fields.GetFieldByInternalName(fieldName);
            field.Group = groupDescriptor;
            field.Update();
            return field;
        }
        return web.Fields[displayName];
    }
 
    public static void CreatePublishingHTMLSiteColumn(SPWeb web, string displayName, string groupDescriptor)
    {
        if (!web.Fields.ContainsField(displayName))
        {
            HtmlField htmlField = new HtmlField(web.Fields, "HTML", displayName)
            {
                Title = displayName,
                Group = groupDescriptor,
                ShowInEditForm = true,
                StaticName = displayName,
                AllowHyperlink = true,
                AllowDeletion = true
            };
 
            web.Fields.Add(htmlField);
 
            //Fix SP defect, update richtext
            htmlField.RichTextMode = SPRichTextMode.FullHtml;
            htmlField.RichText = true;
            htmlField.Update(true);
        }
    }
 
    public static void AddFieldToContentType(SPWeb web,
        SPContentTypeId contentTypeId, string displayName)
    {
        //SP Fix Key cannot be null - retrieve field
        SPField retrievedField = web.Fields[displayName];
 
        if (retrievedField != null)
        {
            SPContentType contentType = web.ContentTypes[contentTypeId];
            if (contentType == null) return;
            if (contentType.Fields.ContainsField(displayName)) return;
            SPFieldLink fieldLink = new SPFieldLink(retrievedField);
            contentType.FieldLinks.Add(fieldLink);
        }
    }
 
    public static void AddExistingFieldToContentType(SPWeb web,
SPContentTypeId contentTypeId, string internalFieldName)
    {
        SPField field = web.Fields.GetField(internalFieldName);
        if (field != null)
        {
            SPContentType contentType = web.ContentTypes[contentTypeId];
            if (contentType == null) return;
            if (contentType.Fields.ContainsField(field.Title)) return;
            SPFieldLink fieldLink = new SPFieldLink(field);
            contentType.FieldLinks.Add(fieldLink);
            contentType.Update();
        }
    }
}

Creating Web Property Bag

Next we will create property bag for our new site (Web scope). Add a new empty element file. P.S: the WebTemplateFeatureId will be your Web Template feature (Site scope)

1
2
3
4
5
6
  <propertybag ParentType="Web">
    <property Name="WebTemplateName" Type="string" Value="CustomWebTemplate" />
    <property Name="WebTemplateFeatureId" Type="string" Value="cb025505-10b4-490b-8185-fe82a2fa44e8" />
  </PropertyBag>
</Elements>

Creating Web Template

Now we add a new module for our web template, which consists of Elements.xml and onet.xml.

For the onet.xml I copied the one from C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\SiteTemplates\BLANKINTERNET\XML without Document templates, Configuration 1 & 2 and Modules tag.
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
  <webtemplate BaseTemplateID="53"
               BaseTemplateName="BLANKINTERNET"
               BaseConfigurationID="0"
               DisplayCategory="Custom"
               Name="CustomWebTemplate"
               Title="My Custom Web Template"
               Locale="3081"
               xmlns="http://schemas.microsoft.com/sharepoint/" />
</Elements>
Onet.xml file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?xml version="1.0" encoding="utf-8" ?>
<!-- _lcid="1033" _version="12.0.2220" _dal="1"
<!-- _LocalBinding -->
<project listdir=""Lists"" quot="" revision=""5"" sharepoint="" title=""$Resources:cmscore,IPPT_Project_Title;"" uiversion=""15"" xmlns:ows=""Microsoft">
  <navbars>
    <navbar id=""1002"/" name=""SharePoint" navbar="" quot="" top="">
    <navbar accesskey="'J'>#LABEL#</a>"" body=""<a" href="'#URL#'" id=""1040"" name=""$Resources:core,SiteSettings_SearchNav_Title;"" separator=""   "">
  </navbar></navbar></navbars>
  <listtemplates>
  </listtemplates>
  <configurations>
    <configuration id=""-1"" name=""NewWeb"/">
    <configuration id=""0"" name=""BLANKINTERNET"">
      <lists>
        <list featureid=""00BFEA71-D1CE-42de-9C63-A44004CE0104"" quicklaunchurl=""$Resources:core,lists_Folder;/$Resources:core,announce_Folder;"" title=""$Resources:core,announceList;"" type=""104"" url=""$Resources:core,lists_Folder;/$Resources:core,announce_Folder;"">
        <list emailalias=""$Resources:core,calendar_EmailAlias;"" featureid=""00BFEA71-EC85-4903-972D-EBE475780106"" quicklaunchurl=""$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;/Calendar.aspx"" title=""$Resources:core,calendarList;"" type=""106"" url=""$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;"">
        <list featureid=""00BFEA71-7E6D-4186-9BA8-C047AC750105"" quicklaunchurl=""$Resources:core,lists_Folder;/$Resources:core,contacts_Folder;"" title=""$Resources:core,contactsList;"" type=""105"" url=""$Resources:core,lists_Folder;/$Resources:core,contacts_Folder;"">
        <list featureid=""00BFEA71-E717-4E80-AA17-D0C71B360101"" quicklaunchurl=""$Resources:core,shareddocuments_Folder;/Forms/AllItems.aspx"" title=""$Resources:core,shareddocuments_Title;"" type=""101"" url=""$Resources:core,shareddocuments_Folder;"">
        <list featureid=""00BFEA71-6A49-43FA-B535-D15C05500108"" quicklaunchurl=""$Resources:core,lists_Folder;/$Resources:core,discussions_Folder;"" title=""$Resources:core,discussions_Title;"" type=""108"" url=""$Resources:core,lists_Folder;/$Resources:core,discussions_Folder;"">
      </list></list></list></list></list></lists>
      <sitefeatures>
        <!-- Workflow Features -->
 
        <!-- Workflow Expiration -->
        <feature id=""C85E5759-F323-4EFB-B548-443D2216EFB5"">
 
        <!-- DLC Workflows -->
        <feature id=""0AF5989A-3AEA-4519-8AB0-85D91ABE39FF"">
 
        <!-- "A44D2AA3-AFFC-4d58-8DB4-F4A3AF053188" -->
        <feature id=""A44D2AA3-AFFC-4d58-8DB4-F4A3AF053188"">
 
        <feature id=""A392DA98-270B-4e85-9769-04C0FDE267AA"">
          <!-- PublishingPrerequisites -->
        </feature>
        <feature id=""7C637B23-06C4-472d-9A9A-7C175762C5C4"">
          <!-- ViewFormPagesLockDown -->
        </feature>
        <feature id=""AEBC918D-B20F-4a11-A1DB-9ED84D79C87E"">
          <!-- PublishingResources -->
          <properties xmlns=""http://schemas.microsoft.com/sharepoint/"">
            <property key=""AllowRss"" value=""false"/">
            <property key=""SimplePublishing"" value=""false"">
            <property key=""EnableModerationOnDocuments"" value=""false"">
            <property key=""EnableModerationOnImages"" value=""false"">
            <property key=""EnableModerationOnReusableContent"" value=""false"">
            <property key=""EnableSchedulingOnDocuments"" value=""false"">
            <property key=""EnableSchedulingOnImages"" value=""false"">
            <property key=""EnableApprovalWorkflowOnDocuments"" value=""false"">
            <property key=""EnableApprovalWorkflowOnImages"" value=""false"">
          </property></property></property></property></property></property></property></property></property></properties>
        </feature>
 
        <feature id=""F6924D36-2FA8-4f0b-B16D-06B7250180FA"">
          <!-- Office SharePoint Server Publishing -->
        </feature>
 
        <feature id=""6E1E5426-2EBD-4871-8027-C5CA86371EAD"">
        </feature>
 
      </feature></feature></feature></sitefeatures>
      <webfeatures>
        <!-- Include the common WSSListTemplateFeatures used by CMS -->
        <feature id=""00BFEA71-DE22-43B2-A848-C05709900100""> </feature>
        <feature id=""00BFEA71-E717-4E80-AA17-D0C71B360101""> </feature>
        <feature id=""00BFEA71-52D4-45B3-B544-B1C71B620109""> </feature>
        <feature id=""00BFEA71-A83E-497E-9BA0-7A5C597D0107""> </feature>
        <feature id=""00BFEA71-4EA5-48D4-A4AD-305CF7030140""> </feature>
        <feature id=""00BFEA71-F600-43F6-A895-40C0DE7B0117""> </feature>
        <feature id=""22A9EF51-737B-4ff2-9346-694633FE4416"">
          <!-- Publishing -->
          <properties xmlns=""http://schemas.microsoft.com/sharepoint/"">
            <property key=""ChromeMasterUrl"" value=""~SiteCollection/_catalogs/masterpage/seattle.master"/">
            <property key=""DefaultPageLayout"" value=""~SiteCollection/_catalogs/masterpage/PageFromDocLayout.aspx"/">
            <property key=""WelcomePageUrl"" value=""$Resources:osrvcore,List_Pages_UrlName;/default.aspx"/">
            <property key=""PagesListUrl"" value="""/">
            <property key=""AvailableWebTemplates"" value=""*-CMSPUBLISHING#0;*-BLANKINTERNET#2;*-ENTERWIKI#0;*-SRCHCEN#0"/">
            <property key=""AvailablePageLayouts"" value="""/">
            <property key=""AlternateCssUrl"" value="""">
            <property key=""SimplePublishing"" value=""false"">
            <property key=""EnableModerationOnPages"" value=""false"">
            <property key=""EnableModerationOnDocuments"" value=""false"">
            <property key=""EnableModerationOnImages"" value=""false"">
            <property key=""EnableSchedulingOnPages"" value=""false"">
            <property key=""EnableSchedulingOnDocuments"" value=""false"">
            <property key=""EnableSchedulingOnImages"" value=""false"">
            <property key=""EnableApprovalWorkflowOnPages"" value=""false"">
            <property key=""EnableApprovalWorkflowOnDocuments"" value=""false"">
            <property key=""EnableApprovalWorkflowOnImages"" value=""false"">
          </property></property></property></property></property></property></property></property></property></property></property></property></property></property></property></property></property></properties>
        </feature>
        <feature id=""541F5F57-C847-4e16-B59A-B31E90E6F9EA"">
          <!-- Per-Web Portal Navigation Properties-->
          <properties xmlns=""http://schemas.microsoft.com/sharepoint/"">
            <property key=""InheritGlobalNavigation"" value=""true"/">
            <property key=""IncludeSubSites"" value=""true"/">
            <property key=""IncludePages"" value=""false"/">
          </property></property></property></properties>
        </feature>
        <feature id=""94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB"">
          <!-- Office SharePoint Server Publishing -->
        </feature>
         
        <!-- Property bag feature-->
        <feature id=""9b3f6f3f-768b-4873-8e5d-dace9c852c65""></feature>
      </webfeatures>
      <modules>
        <module name=""Home"">
      </module></modules>
    </configuration>
  </configuration></configurations>
  <modules>
    <module name=""Home"" path="""" url=""$Resources:osrvcore,List_Pages_UrlName;"">
      <file type=""GhostableInLibrary"" url=""default.aspx"">
        <property name=""Title"" value=""$Resources:cmscore,IPPT_HomeWelcomePage_Title;"">
        <property name=""PublishingPageLayout"" value=""~SiteCollection/_catalogs/masterpage/intranet/CustomContentPage.aspx"">
      </property></property></file>
    </module>
  </modules>
</project>

Notice that I added the property bag feature and my default.aspx module that uses my custom page layout.

WebProvisioned receiver

The last thing we want to do is to configure our new created subsite to match the settings we want. Add a receiver module for the WebProvisioned feature receiver. Mark the receiver as Synchronous.
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
  <receivers >
      <receiver>
        <name>CustomWebTemplateWebReceiverWebProvisioned</Name>
        <type>WebProvisioned</Type>
        <assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
        <class>Solution.Receivers.CustomWebTemplateWebReceiver.CustomWebTemplateWebReceiver</Class>
        <sequencenumber>10000</SequenceNumber>
        <synchronization>Synchronous</Synchronization>
      </Receiver>
  </Receivers>
</Elements>
And the receiver code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
public class CustomWebTemplateWebReceiver : SPWebEventReceiver
    {
        /// <summary>
        /// A site was provisioned.
        /// </summary>
        public override void WebProvisioned(SPWebEventProperties properties)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWeb web = properties.Web;
 
                    if (web.AllProperties.ContainsKey("WebTemplateName"))
                    {
                        if (web.AllProperties["WebTemplateName"].ToString() == "CustomWebTemplate")
                        {
                            web.AllowUnsafeUpdates = true;
 
                            SPWeb rootSite = web.Site.RootWeb;
 
                            web.MasterUrl = rootSite.MasterUrl;
                            web.CustomMasterUrl = rootSite.CustomMasterUrl;
                            web.Update();
 
                            EnableCustomCT(web);
                            UpdateDefaultPageTitle(web);
                            UpdateNavigation(web);
 
                            web.AllowUnsafeUpdates = false;
                        }
                    }
                });
            }
            catch (Exception e)
            { }
        }
 
        private void EnableCustomCT(SPWeb web)
        {
            SPList pagesList = web.Lists["Pages"];
            SPContentType CustomCT = web.Site.RootWeb.ContentTypes["CustomCT"];
 
            if (pagesList != null && CustomCT != null)
            {
                pagesList.ContentTypes.Add(CustomCT);
                pagesList.EnableModeration = true;
                pagesList.Update();
                pagesList.RootFolder.UniqueContentTypeOrder = null;
                pagesList.RootFolder.Update();
 
                //Get a list of content types for the "new" drop down on the list
                SPContentType[] arrContentTypes = new SPContentType[pagesList.ContentTypes.Count - 1];
                int arrContentTypesCount = 0;
                int iContentTypeCount = pagesList.ContentTypes.Count;
 
                for (int iCount = 0; iCount < iContentTypeCount; iCount++)
                {
                    if (pagesList.ContentTypes[iCount].Name != "Folder")
                    {
                        arrContentTypes[arrContentTypesCount] = pagesList.ContentTypes[iCount];
                        arrContentTypesCount++;
                    }
                }
 
                //Set the content types for the "new" drop down list
                pagesList.RootFolder.UniqueContentTypeOrder = arrContentTypes;
                pagesList.RootFolder.Update();
            }
        }
 
        private void UpdateDefaultPageTitle(SPWeb web)
        {
            SPContentType customCT = web.Site.RootWeb.ContentTypes["CustomCT"];
            string checkInComment = "Update page title";
 
            //Change page title
            if (PublishingWeb.IsPublishingWeb(web))
            {
                var pubWeb = PublishingWeb.GetPublishingWeb(web);
 
                PublishingPage homePage = PublishingPage.GetPublishingPage(pubWeb.DefaultPage.Item);
                if (homePage.ListItem.File.CheckOutType == SPFile.SPCheckOutType.None)
                {
                    homePage.CheckOut();
                }
 
                homePage.Title = web.Title;
 
                //Update content type since webtemplate doesn't pick the correct one
                if (customCT != null)
                {
                    homePage.ListItem["ContentTypeId"] = customCT.Id;
                    homePage.ListItem["ContentType"] = customCT.Name;
                }
 
                homePage.Update();
                homePage.CheckIn(checkInComment);
                SPFile pageFile = homePage.ListItem.File;
                pageFile.Publish(checkInComment);
                pageFile.Approve(checkInComment);
            }
        }
 
        private void UpdateNavigation(SPWeb web)
        {
            var pubWeb = PublishingWeb.GetPublishingWeb(web);
            var webNavigationSettings = new WebNavigationSettings(web);
 
            webNavigationSettings.CurrentNavigation.Source = StandardNavigationSource.PortalProvider;
            pubWeb.Navigation.ShowSiblings = true;
            pubWeb.Navigation.CurrentIncludeSubSites = true;
            pubWeb.Navigation.CurrentIncludePages = true;
            webNavigationSettings.Update();
            pubWeb.Update();
 
            //Add Shared Documents, Announcements, Team Discussion, Calendar list
            NavigationHelper.AddHeadingToQuickLaunch(web, "Calendar", SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/Lists/Calendar/calendar.aspx"), false);
            NavigationHelper.AddHeadingToQuickLaunch(web, "Team Discussion", SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/Lists/Team Discussion/AllItems.aspx"), false);
            NavigationHelper.AddHeadingToQuickLaunch(web, "Announcements", SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/Lists/Announcements/AllItems.aspx"), false);
            NavigationHelper.AddHeadingToQuickLaunch(web, "Shared Documents", SPUrlUtility.CombineUrl(web.ServerRelativeUrl, "/Shared Documents/Forms/AllItems.aspx"), false);
        }
    }

Navigation helper (thanks to this article) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public static class NavigationHelper
    {
        //The parentNode here represents either an existent link or the root SPWeb.Navigation.QuickLaunch object.
        public static SPNavigationNode AddLinkToQuickLaunch(SPNavigationNode parentNode,
                                        string title, string url, bool isExternal)
        {
            SPNavigationNode node = new SPNavigationNode(title, url, isExternal);
            parentNode.Children.AddAsLast(node);
 
            // refresh navigation node just in case
            node = parentNode.Navigation.GetNodeById(node.Id);
            return node;
        }
 
        //Set url to "javascript:window.goback(0)" for heading that does not link
        public static SPNavigationNode AddHeadingToQuickLaunch(SPWeb spWeb, string headingName, string url, bool addLast)
        {
            SPNavigationNodeCollection quicklaunchNav = spWeb.Navigation.QuickLaunch;
 
            SPNavigationNode headingNode = new SPNavigationNode(headingName, url, true);
 
            if (addLast)
            {
                headingNode = quicklaunchNav.AddAsLast(headingNode);
            }
            else
            {
                headingNode = quicklaunchNav.AddAsFirst(headingNode);
            }
 
            //turn the node into Heading
            TurnIntoHeading(headingNode);
 
            headingNode.Update();
 
            // refresh navigation node just in case
            headingNode = spWeb.Navigation.GetNodeById(headingNode.Id);
            return headingNode;
        }
 
        public static void TurnIntoHeading(SPNavigationNode node)
        {
            node.Properties["NodeType"] = "Heading";
 
            node.Properties["LastModifiedDate"] = DateTime.Now;
            node.Properties["Target"] = "";
            node.Properties["vti_navsequencechild"] = "true";
            node.Properties["UrlQueryString"] = "";
            node.Properties["CreatedDate"] = DateTime.Now;
            node.Properties["Description"] = "";
            node.Properties["UrlFragment"] = "";
            node.Properties["Audience"] = "";
        }
    }

That's all I have to do :)

HTH,
Andreas

Comments

Popular posts from this blog

SharePoint 2013 anonymous access add attachments to list item

CRM Plugin - Parent and Child Pipeline