Adding ContentBlock to a Page via Fluent API
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.
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
Thanks Sabrie,
The issue is resolved now. I had to set the "zoneName" parameter to the correct value as shown in this screencast.
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];
.Do(c =>
c.PlaceHolder = GetContentPlaceholderId(templateId,
"Content"
, 1);
c.SiblingId = GetLastControlInPlaceHolderInPageId(pageId, c.PlaceHolder);
)
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!
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.