+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Adding ContentBlock to a Page via Fluent API

Adding ContentBlock to a Page via Fluent API

6 posts, 0 answered
  1. Abe
    Abe avatar
    3 posts
    Registered:
    29 Dec 2014
    18 Mar 2015
    Link to this post

    Hello Sitefinity Team,

     I am trying to create Sitefinity pages via Fluent API and populate it with content by adding a ContenBlock control to the page. Everything seems fine except for the fact that the ContentBlock ends in the wrong place on the page, even though I specify the Placeholder name. The pages are based on built-in Sitefinity templates.

    Here's the code snippet I'm using to create the page:

     

    var content = new ContentBlock()
     {
         Html = GetHtmlContent(),
         IsShared = false,
         Enabled = true,
     };
     
     Guid pageId = new Guid();
     App.WorkWith()
         .Page()
         .CreateNewStandardPage(parentId, pageId)
         .Do(page =>
         {
             page.Title = "Test page 1";
             page.UrlName = "tp-1";
             page.Name = "TestPage";
             page.Description = "";
             page.GetPageData().HtmlTitle = "This is a test";
             page.ShowInNavigation = false;
             page.DateCreated = DateTime.Now;
             page.Crawlable = true;
             page.RequireSsl = false;
         })
         .CheckOut()
         .SetTemplateTo(Guid.Parse("f669d9a7-009d-4d83-bbbb-000000000002"))
         .Control()
             .CreateNew(content, "Content")
             .Do(c =>
                 {
                     c.PlaceHolder = "Content";
                 })
             .SaveChanges()
             .Done()
         .CheckIn()
         .SaveChanges();

     Any pointers would be greatly appreciated.

  2. Sabrie Nedzhip
    Sabrie Nedzhip avatar
    534 posts
    Registered:
    07 Dec 2016
    23 Mar 2015
    Link to this post
    Hello Abe,

    Currently we do not have a sample on how to add a control to a page using the Fluent API. What I can suggest is to refer to the following articles from our documentation for more details and sample code on how you can achieve this using the Native API.

    Regards,
    Sabrie Nedzhip
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  3. Abe
    Abe avatar
    3 posts
    Registered:
    29 Dec 2014
    23 Mar 2015 in reply to Sabrie Nedzhip
    Link to this post

    Thanks Sabrie,

     

    The issue is resolved now. I had to set the "zoneName" parameter to the correct value as shown in this screencast.

  4. Sabrie Nedzhip
    Sabrie Nedzhip avatar
    534 posts
    Registered:
    07 Dec 2016
    30 Mar 2015
    Link to this post
    Hello Abe,

    Thank for you for sharing your solution with the community and for the detailed video you have recorded.

    I have also researched this on my side and here is another sample code you can use to place a content block on a page programatically:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Telerik.Sitefinity;
    using Telerik.Sitefinity.Abstractions;
    using Telerik.Sitefinity.Modules.GenericContent.Web.UI;
    using Telerik.Sitefinity.Modules.Pages;
    using Telerik.Sitefinity.Pages.Model;
    using Telerik.Sitefinity.Workflow;
     
    namespace SitefinityWebApp
    {
        public partial class AddContentBlockToPageFluenApi : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var content = new ContentBlock()
                {
                    Html = "<div>This is my content</div>",
                    IsShared = false,
                    Enabled = true,
                };
     
                Guid pageId = Guid.NewGuid();
                var pageDataId = Guid.NewGuid();
     
                App.WorkWith()
                    .Page()
                    .CreateNewStandardPage(SiteInitializer.CurrentFrontendRootNodeId, pageId, pageDataId)
                    .Do(page =>
                    {
                        page.Title = "Test page 3";
                        page.UrlName = "tp-3";
                        page.Name = "Test page 3";
                        page.Description = "";
                        page.GetPageData().HtmlTitle = "This is a test";
                        page.ShowInNavigation = false;
                        page.DateCreated = DateTime.Now;
                        page.Crawlable = true;
                        page.RequireSsl = false;
                    })
                    .SaveChanges();
     
                // Publish
                var bag = new Dictionary<string, string>();
                bag.Add("ContentType", typeof(PageNode).FullName);
                WorkflowManager.MessageWorkflow(pageId, typeof(PageNode), null, "Publish", false, bag);
     
                var templateId = new Guid("f669d9a7-009d-4d83-bbbb-000000000002");
                App.WorkWith().Page(pageId).AsStandardPage()
                    .CheckOut()
                    .SetTemplateTo(templateId)
                    .Control()
                        .CreateNew(content, "Content")
                        .Do(c =>
                        {
                            c.PlaceHolder = GetContentPlaceholderId(templateId, "Content", 1);
                            c.SiblingId = GetLastControlInPlaceHolderInPageId(pageId, c.PlaceHolder);
                        })
                        .SaveChanges()
                        .Done()
                    .CheckIn()
                    .Publish()
                    .SaveChanges();
     
                //App.WorkWith().Page(pageId).AsStandardPage().CheckOut().UndoDraft().SaveChanges();              
            }
     
            private static Guid GetLastControlInPlaceHolderInPageId(Guid pageId, string placeHolder)
            {
                var pageManager = PageManager.GetManager();
                var page = pageManager.GetPageNodes().Where(p => p.Id == pageId).SingleOrDefault();
                var pageDraft = pageManager.EditPage(page.GetPageData().Id);
     
                var id = Guid.Empty;
                PageDraftControl control;
     
                var controls = new List<PageDraftControl>(pageDraft.Controls.Where(c => c.PlaceHolder == placeHolder));
     
                while (controls.Count > 0)
                {
                    control = controls.Where(c => c.SiblingId == id).SingleOrDefault();
                    id = control.Id;
     
                    controls.Remove(control);
                }
     
                return id;
            }
     
            public static string GetContentPlaceholderId(Guid templateId, string zoneName, int position)
            {
                var pageManager = PageManager.GetManager();
                var contentAndSideBar = pageManager.GetTemplate(templateId).Controls.FirstOrDefault(x => x.Caption.Contains(zoneName));
                return contentAndSideBar.PlaceHolders[position];
     
            }
        }       
    }

    In order to place the widget on the desired placeholder, you need to specify the zone name which is the for example the Caption of the placeholder and then the position. Please refer to the underlined part of the code below:

    .Do(c =>
                        {
                            c.PlaceHolder = GetContentPlaceholderId(templateId, "Content", 1);
                            c.SiblingId = GetLastControlInPlaceHolderInPageId(pageId, c.PlaceHolder);
                        })

    Please also refer to the attached screenshot for more details about the positions.

    Using the code sample above, the content block widget will be added in the placeholder with zone name Content and with position 1.

    Regards,
    Sabrie Nedzhip
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  5. Joseph
    Joseph avatar
    2 posts
    Registered:
    01 Jul 2014
    16 Apr 2015 in reply to Sabrie Nedzhip
    Link to this post

    Thanks for this post. It was a big help in my case. Could you add how you would set the default permissions on this control? When a control is created through the Fluent API like this, all of it's permissions are set to administrator only. I'm migrating roughly 800 pages and need the default permissions for a content block applied.

    When I try to apply permissions, I get the following error:

    Object references between two different object scopes are not allowed. The object 'Telerik.Sitefinity.Security.Model.Permission' is already managed by 'ObjectScopeImpl 0x48 OpenAccessRuntime.EnlistableObjectScope' and was tried to be managed again by 'ObjectScopeImpl 0x49 OpenAccessRuntime.EnlistableObjectScope'.

    Here's my code:

    App.WorkWith().Page(pageId).AsStandardPage()
        .CheckOut()
        .SetTemplateTo(templateId)
        .Control()
            .CreateNew(content, "Content")
            .Do(c =>
                {
                    c.PlaceHolder = primaryContentPlaceholder;
                    c.Caption = "Primary Content";
                    c.SetDefaultPermissions(pageManager);
                })
            .SaveChanges()
            .Done()
        .CheckIn()
        .SaveChanges();

    If I remove the following line, I don't get the error but I don't get the desired permissions either:

    c.SetDefaultPermissions(pageManager);

    Thanks!

  6. Joseph
    Joseph avatar
    2 posts
    Registered:
    01 Jul 2014
    16 Apr 2015 in reply to Joseph
    Link to this post
    I fixed it on my own. For the sake of cleanup to post my code here, I moved some extra logic I had out of the API call and all is now well.
6 posts, 0 answered