Cloning Objects in Kentico

   —   

Developers should always be looking for ways to code smarter and more effectively. Often when developing with Kentico, objects need to be replicated within an environment. Luckily, Kentico provides some great cloning capabilities that developers can leverage to simplify their development and replicate their configurations.

Many of the interfaces inside the Kentico administration site allow developers to clone objects and configurations quickly. This enables the fast replication of page types, users, and many other objects within the system, all via the API behind the scenes. Packed with several options and parameters, the API allows objects to be cloned with or without child objects, bindings to be preserved, and a number of other object-specific actions.

You can also call a method to fire before and after the cloned object is inserted into the database. This can be especially helpful if you need to set additional properties when the cloned object is created.

In this blog, I wanted to provide some code samples to replicate various objects in the system.

Setup

In order to demonstrate the cloning API, I created a custom module within my site. This was done following the standard module development example here.

After creating the initial module, I added some uniselectors for working with different types of objects within the system.

Module UI

I also added some additional fields where I could specify the cloned object’s display name, code name, and whether or not child objects were to be cloned.

// Prepares the settings used for the cloning process. CloneSettings settings = new CloneSettings() { // Sets the cloned object names. CodeName = txtCodeName.Text, DisplayName = txtDisplayName.Text, IncludeChildren = cbIncludeChildren.Checked };

Countries

Cloning countries via the API is a very simple process, especially because it’s already covered in the document here. This is the code that I used to clone the selected country:

// Gets the country to be cloned. CountryInfo country = CountryInfoProvider.GetCountryInfo(ValidationHelper.GetInteger(uniCountry.Value, 0)); if (country != null) { // Registers a callback method that performs additional actions before the clone is added. settings.BeforeCloneInsertCallback = ChangeCountryCodes; // Clones the object according to the defined settings and returns the cloned object BaseInfo clonedcountry = country.Generalized.InsertAsClone(settings); strMessage = "Country cloned!"; strDescription = "Object '" + country.CountryDisplayName + "' was successfully cloned as " + clonedcountry.GetValue("CountryDisplayName") + "'"; }

Additionally, I leveraged the BeforeCloneInsertCallback event to update additional properties on the cloned object after it gets created.

private void ChangeCountryCodes(CloneSettings settings, BaseInfo cloneToBeInserted) { // Changes the values of additional fields before the clone is inserted to the DB. CountryInfo country = cloneToBeInserted as CountryInfo; if (country != null) { country.CountryThreeLetterCode = "XXX"; country.CountryTwoLetterCode = "XX"; } }

Here is a before and after of the list of countries. Note that because I selected IncludeChildren, all of the states associated with the country were also cloned.

Country 1

Country 2

Country 3

Page Types

Page types are another complex type of object that would benefit from being cloned via the API. Because page types can have fields, transformations, and queries associated with them, cloning an existing page type could save a lot of clicks and expedite development.

Here is the code to clone a Page Type object.

// Gets the page type to be cloned. DataClassInfo pagetype = DataClassInfoProvider.GetDataClassInfo(ValidationHelper.GetInteger(uniPageType.Value, 0)); if (pagetype != null) { // Update the class name settings.CodeName = "CMS." + settings.CodeName; // Clones the object according to the defined settings and returns the cloned object BaseInfo clonedpagetype = pagetype.Generalized.InsertAsClone(settings); strMessage = "Page Type cloned!"; strDescription = "Object '" + pagetype.ClassDisplayName + "' was successfully cloned as " + clonedpagetype.GetValue("ClassDisplayName") + "'"; }

And here is the before and after showing the cloned page type.

Page Type 1

Page Type 2

Page Type 3

Workflows

Seeing how the first two examples are pretty much the same, you can imagine the rest of the calls are very similar. To clone a workflow, I just need to get the selected workflow object and call the same code.

// Gets the workflow to be cloned. WorkflowInfo workflow = WorkflowInfoProvider.GetWorkflowInfo(ValidationHelper.GetInteger(uniWorkflow.Value, 0)); if (workflow != null) { // Clones the object according to the defined settings and returns the cloned object BaseInfo clonedworkflow = workflow.Generalized.InsertAsClone(settings); strMessage = "Workflow cloned!"; strDescription = "Object '" + workflow.WorkflowDisplayName + "' was successfully cloned as " + clonedworkflow.GetValue("WorkflowDisplayName") + "'"; }

And here is the before and after of the workflow within the site.

Workflow 1

Workflow 2

Workflow 3

Reports

Reports are another object that can be cloned easily. Because each report can have numerous tables and charts associated with it, it’s pretty essential to include child objects so all of these pieces get cloned, as well.

// Gets the report to be cloned. ReportInfo report = ReportInfoProvider.GetReportInfo(ValidationHelper.GetInteger(uniReport.Value, 0)); if (report != null) { // Clones the object according to the defined settings and returns the cloned object BaseInfo clonedreport = report.Generalized.InsertAsClone(settings); strMessage = "Report cloned!"; strDescription = "Object '" + report.ReportDisplayName + "' was successfully cloned as " + clonedreport.GetValue("ReportDisplayName") + "'"; }

Here is the before and after showing all of the report objects cloned.

Report 1

Report 2

Report 3

Moving Forward

As you can see, it’s really easy to leverage the API to clone objects. The ability to clone child objects along with the parent objects can save a ton of time, especially when working with really complex data objects such as page types and templates. I’ve used this approach in the past when building functionality to replicate a section of pages and classes within a site, and it greatly simplified the development. Good luck!

Get the code

Exported module

This blog is intended for informational purposes only and provides an example of one of the many ways to accomplish the described task. Always consult Kentico Documentation for the best practices and additional examples that may be more effective in your specific situation.

Share this article on   LinkedIn

Bryan Soltis

Hello. I am a Technical Evangelist here at Kentico and will be helping the technical community by providing guidance and best practices for all areas of the product. I might also do some karaoke. We'll see how the night goes...