Copying a Page, programatically
Hello,
We have a requirement that we allow an admin user to select a page group (Page A) from a custom module, and duplicate that page group under another page group (Page B). I was hoping that someone had done this before, and might have an example of how they achieved this?
Hello Travis,
Please find below a short sample I've prepared for you - it will take the Page group title as an argument and will copy it, and its children under a specified page (currently ti just duplicates them with a _Copy string in the title, but you can modify this as per your specific requirements.
public
void
DuplicatePageAndChildPages(
string
pageTitle)
var pageToDuplicate = App.WorkWith().Pages().ThatArePublished().Where(p => p.Title == pageTitle).Get().SingleOrDefault();
var myDuplicatedPage = App.WorkWith().Page(pageToDuplicate.Id).Duplicate().Do(p =>
p.Title = pageToDuplicate.Title +
" Copy"
;
p.UrlName = pageToDuplicate.UrlName +
"_copy"
;
p.ShowInNavigation =
true
;
if
(p.Page !=
null
)
p.Page.Title = p.Title;
).SaveAndContinue().Get();
WorkflowManager.MessageWorkflow(myDuplicatedPage.Id,
typeof
(PageNode),
null
,
"Publish"
,
false
,
new
Dictionary<
string
,
string
>());
var myChildPages = App.WorkWith().Pages().ThatArePublished().Where(p => p.ParentId == pageToDuplicate.Id).Get();
if
(myChildPages !=
null
&& myChildPages.Count() > 0)
foreach
(var pg
in
myChildPages)
var myDuplicatedChild = App.WorkWith().Page(pg.Id).Duplicate().Do(p =>
p.ParentId = myDuplicatedPage.Id;
p.Title = pg.Title +
" Copy"
;
p.UrlName = pg.UrlName +
"_copy"
;
p.ShowInNavigation =
true
;
if
(p.Page !=
null
)
p.Page.Title = p.Title;
).SaveAndContinue().Get();
WorkflowManager.MessageWorkflow(myDuplicatedChild.Id,
typeof
(PageNode),
null
,
"Publish"
,
false
,
new
Dictionary<
string
,
string
>());
being new in sitefinity development, could you also post how to integrate this piece of code with the UI. or at least point to the right direction?
I've been trying to figure out how to add an additional action to the backend pages treeview -> actions context menu and i can't seem to find a code sample.
Hello Travis,
Please take a look at the second part of this blog post - Adding a new Action command in the individual Content item Actions menu , I believe you might find it useful.
Greetings,
Boyan Barnev
the Telerik team
Thanks a lot, i'll check it out
Hi again,
I've followed the example in the post yet i can't seem to bind the new action to do something:
First things first, i added a new Action in:
Setting->Advanced->ContentView->Controls->FrontendPages->Views->FrontendPagesListView->ViewModes->TreeTable->
Columns->ActionLinkText->MenuItems
and added a new action named duplicateX. The properties set are exactly as the example says, only instead of "duplicate" i put "duplicateX" since a duplicate entry allready exists.
This part works, the new action exists in the action menu. (but it will not appear for group pages and i can't find the configuration to modify this behaviour)
I made a new service:
[ServiceContract]
public interface IExtendedPagesService
[WebInvoke(Method = "POST", UriTemplate = "pageId/duplicateX/", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
string DuplicatePage(string pageId);
public class ExtendedPagesService : IExtendedPagesService
public string DuplicatePage(string pageId)
....
protected void Application_Start(object sender, EventArgs e)
Bootstrapper.Initialized += new EventHandler<
Telerik.Sitefinity.Data.ExecutedEventArgs
>(Bootstrapper_Initialized);
void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
SystemManager.RegisterWebService(typeof(ExtendedPagesService), "Sitefinity/Services/Pages/ExtendedPagesService.svc");
function duplicateXCommandHandler(sender, args)
if (args._commandName == "duplicateX")
jQuery.ajax(
type: "POST",
url: sender._baseUrl + "Sitefinity/Services/Pages/ExtendedPagesService.svc/" + args._dataItem.Id + "/duplicateX/",
contentType: "application/json; charset=utf-8",
dataType: "json",
processdata: false,
success: function (data)
if (data != "ERROR")
args._dataItem.Id = data;
//sender.get_itemsGrid().executeCommand("edit", args._dataItem, [data], args._itemElement, null, null);
// Or call the line below instead to just refresh the grid
sender.get_itemsGrid().dataBind();
,
error: function (data)
);
function frontendPagesListLoaded(sender, args)
sender.add_itemCommand(duplicateXCommandHandler);
So getting back to the page duplication problems, the above code did not resolve the issues. in fact it created a new one. the original problem was that we were getting errors that looked like:
PageNode rootNode = manager.GetPageNode(SiteInitializer.FrontendRootNodeId);
if (NodeToCreateUnder == Guid.Empty && rootNode != null)
NodeToCreateUnder = rootNode.Id;
if (rootNode != null && NodeToCopyFrom != Guid.Empty && NodeToCreateUnder != Guid.Empty)
PageNode copyFromNode = manager.GetPageNode(NodeToCopyFrom);
newRootNode = manager.GetPageNode(NodeToCreateUnder);
try
newPageNode = App.WorkWith().Page(copyFromNode.Id).Duplicate().Do(p =>
if (p.Page != null)
p.Page.Title = NewRoot_Title;
p.Page.Description = NewRoot_Description;
p.Page.HtmlTitle = NewRoot_HTMLTitle;
p.Name = NewRoot_Title;
p.Description = NewRoot_Description;
p.Title = NewRoot_Title;
p.ParentId = NodeToCreateUnder;
p.Ordinal = copyFromNode.Ordinal;
p.AllowMultipleUrls = false;
p.Urls.Clear();
p.UrlName = Regex.Replace(NewRoot_Title.ToLower(), @"[^\w\-\!\$\'\(\)\=\@\d_]+", "-");
p.DateCreated = DateTime.UtcNow;
p.LastModified = DateTime.UtcNow;
).SaveAndContinue().Get();
if (newPageNode != null)
if (newPageNode.NodeType != NodeType.Group)
WorkflowManager.MessageWorkflow(newPageNode.Id, typeof(PageNode), null, "Publish", false, new Dictionary<
string
, string>());
catch newPageNode = null;
if (newPageNode != null)
_BuildChildNodes(newPageNode, NodeToCopyFrom, newPartner);
_BuildChildNodes(PageNode rootNode, Guid NodeToCopyFrom, PartnerItem newPartner)
List<
PageNode
> nodesToCopyList = App.WorkWith().Pages().ThatArePublished().Where(p => p.ParentId == NodeToCopyFrom).Get().ToList();
List<
Guid
> NewPages = new List<
Guid
>();
List<
Guid
> OldPages = new List<
Guid
>();
foreach (PageNode pn in nodesToCopyList)
try
PageNode myDuplicatedPage = App.WorkWith().Page(pn.Id).Duplicate().Do(p =>
p.ParentId = rootNode.Id;
p.Ordinal = pn.Ordinal;
p.AllowMultipleUrls = false;
p.Urls.Clear();
p.UrlName = Regex.Replace(pn.Title.ToLower(), @"[^\w\-\!\$\'\(\)\=\@\d_]+", "-");
p.DateCreated = DateTime.UtcNow;
p.LastModified = DateTime.UtcNow;
).SaveAndContinue().Get();
if (myDuplicatedPage.NodeType != NodeType.Group)
WorkflowManager.MessageWorkflow(myDuplicatedPage.Id, typeof(PageNode), null, "Publish", false, new Dictionary<
string
, string>());
NewPages.Add(myDuplicatedPage.Id);
OldPages.Add(pn.Id);
catch
for (int i = 0; i <
NewPages.Count
; i++)
PageNode
newnode
=
App
.WorkWith().Pages().ThatArePublished().Where(p => p.Id == NewPages[i]).Get().FirstOrDefault();
if (newnode != null)
_BuildChildNodes(newnode, OldPages[i], newPartner);
UPDATE
UPDATE