Kentico Cloud Content Management .NET SDK
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.github
KenticoCloud.ContentManagement.Helpers.Tests
KenticoCloud.ContentManagement.Helpers
KenticoCloud.ContentManagement.Tests
KenticoCloud.ContentManagement
.gitattributes
.gitignore
CODE_OF_CONDUCT.md
CONTRIBUTING.md
KenticoCloud.ContentManagement.sln
LICENSE
README.md

README.md

Kentico Cloud Content Management .NET SDK

Build status NuGet NuGet Forums

Summary

The Kentico Cloud Content Management .NET SDK is a client library used for managing content in Kentico Cloud. It provides read/write access to your Kentico Cloud projects.

You can use the SDK in the form of a NuGet package to migrate existing content into your Kentico Cloud project or update content in your content items. You can import content items, their language variants, and assets.

The Content Management SDK does not provide any content filtering options and is not optimized for content delivery. If you need to deliver larger amounts of content we recommend using the Delivery SDK instead.

You can head over to our Developer Hub for the complete Content Management API Reference.

The SDK targets the .NET Standard 2.0, which means it can be used in .NET Framework 4.6.1 projects and above, and .NET Core 2.0 projects and above.

Prerequisites

To manage content in a Kentico Cloud project via the Content Management API, you first need to activate the API for the project. See our documentation on how you can activate the Content Management API.

You also need to prepare the structure of your Kentico Cloud project before importing your content. This means defining the Content types of the items you want to import. You might also need to set up your Languages, Taxonomy or Sitemap locations (if you plan to use them).

Using the ContentManagementClient

The ContentManagementClient class is the main class of the SDK. Using this class, you can import, update, view and delete content items, language variants, and assets in your Kentico Cloud projects.

To create an instance of the class, you need to provide a project ID and a valid Content Management API Key.

ContentManagementOptions options = new ContentManagementOptions
{
    ProjectId = "bb6882a0-3088-405c-a6ac-4a0da46810b0",
    ApiKey = "ew0...1eo"
};

// Initializes an instance of the ContentManagementClient client
ContentManagementClient client = new ContentManagementClient(options);

Once you create a ContentManagementClient, you can start managing content in your project by calling methods on the client instance. See Importing content items for details.

Codename vs. ID vs. External ID

Most methods of the SDK accept an Identifier object that specifies which content item, language variant, or asset you want to perform the given operation on. There are 3 types of identification you can use to create the identifier:

ContentItemIdentifier identifier = ContentItemIdentifier.ByCodename("on_roasts");
ContentItemIdentifier identifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));
ContentItemIdentifier identifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");
  • Codenames are generated automatically by Kentico Cloud based on the object's name. They can make your code more readable but are not guaranteed to be unique. Use them only when there is no chance of naming conflicts.
  • (internal) IDs are random GUIDs assigned to objects by Kentico Cloud at the moment of import/creation. They are unique and generated by the system for existing objects. This means you cannot use them to refer to content that is not imported yet.
  • External IDs are string-based custom identifiers defined by you. Use them when importing a batch of cross-referencing content. See Importing Modular and linked content for more details.

Strongly-typed models of your content

The ContentManagementClient also supports working with strongly-typed models. You can generate strongly-typed models from your content types using the Kentico Cloud model generator utility.

// Elements to update
ArticleModel stronglyTypedElements = new ArticleModel
{
    Title = "On Roasts",
    PostDate = new DateTime(2017, 7, 4)
};

// Upserts a language variant of a content item
ContentItemVariantModel<ArticleModel> response = await client.UpsertContentItemVariantAsync<ArticleModel>(identifier, stronglyTypedElements);

You can also use anonymous objects to achieve the same result:

// Elements to update
var elements = new
{
    title = "On Roasts",
    post_date = new DateTime(2017, 7, 4)
};
ContentItemVariantUpsertModel upsertModel = new ContentItemVariantUpsertModel() { Elements = elements };

// Upserts a language variant of a content item
ContentItemVariantModel<CafeModel> response = await client.UpsertContentItemVariantAsync<CafeModel>(identifier, upsertModel);

However, we encourage you to use strongly-typed models for their convenience and type safety. Examples in this document use strongly-typed models where possible.

Quick start

Importing content items

Importing content items is a 2 step process, using 2 separate methods:

  1. Creating an empty content item which serves as a wrapper for your content.
  2. Adding content inside a language variant of the content item.

Each content item can consist of several localized variants. The content itself is always part of a specific language variant, even if your project only uses one language. See our tutorial on Importing to Kentico Cloud for a more detailed explanation.

1. Creating a content item

// Creates an instance of the Content Management client
ContentManagementClient client = new ContentManagementClient(options);

// Defines the content item to import
ContentItemCreateModel item = new ContentItemCreateModel()
{
    Name = "On Roasts",
    Type = ContentTypeIdentifier.ByCodename("article"),
    SitemapLocations = new[] { SitemapNodeIdentifier.ByCodename("articles") }
};

// Adds the content item to your project in Kentico Cloud
ContentItemModel response = await client.CreateContentItemAsync(item);

Kentico Cloud will generate an internal ID and codename for the (new and empty) content item and include it in the response. In the next step, we will add the actual (localized) content.

2. Adding language variants

To add localized content, you have to specify:

  • The content item you are importing into.
  • The language variant of the content item.
  • The content elements of the language variant you want to add or update. Omitted elements will remain unchanged.
// Defines the content elements to update
ArticleModel stronglyTypedElements = new ArticleModel
{
    Title = "On Roasts",
    PostDate = new DateTime(2017, 7, 4),
    BodyCopy = @"
        <h1>Light Roasts</h1>
        <p>Usually roasted for 6 - 8 minutes or simply until achieving a light brown color. This method
        is used for milder coffee  varieties and for coffee tasting. This type of roasting allows the natural
        characteristics of each coffee to show. The aroma of coffees produced from light roasts is usually
        more intense.The cup itself is more acidic and the concentration of caffeine is higher.</p>
    ",
    RelatedArticles = new [] { ContentItemIdentifier.ByCodename("which_brewing_fits_you_") },
    UrlPattern = "on-roasts",
    Personas = new [] { TaxonomyTermIdentifier.ByCodename("barista") }
};

// Specifies the content item and the language variant
ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByCodename("on_roasts");
LanguageIdentifier languageIdentifier = LanguageIdentifier.ByCodename("en-US");
ContentItemVariantIdentifier identifier = new ContentItemVariantIdentifier(itemIdentifier, languageIdentifier);

// Upserts a language variant of your content item
ContentItemVariantModel<ArticleModel> response = await client.UpsertContentItemVariantAsync<ArticleModel>(identifier, stronglyTypedElements);

Importing assets

Importing assets using the Content Management API is usually a 2-step process:

  1. Uploading a file to Kentico Cloud.
  2. Creating a new asset using the given file reference.

This SDK, however, simplifies the process and allows you to upload assets using a single method:

// Defines the description of an asset
AssetDescription assetDescription = new AssetDescription
{
    Description = "Description of the asset in English Language",
    Language = LanguageIdentifier.ByCodename("en-US")
};

IEnumerable<AssetDescription> descriptions = new [] { assetDescription };

// Title of a new asset
string title = "Asset title";

// Defines the asset to upsert
AssetUpdateModel asset = new AssetUpdateModel
{
    Descriptions = descriptions,
    Title = title
};

string filePath = "‪C:\\Users\\Kentico\\Desktop\\puppies.png";
string contentType = "image/png";

// Uploads the file and links it to a new asset
AssetModel response = await client.CreateAssetAsync(new FileContentSource(filePath, contentType), asset);

Importing Modular and linked content

The content you are importing will often contain references to other pieces of imported content. A content item can reference assets or point to other content items using modular content elements or links. To avoid having to import objects in a specific order (and solve problems with cyclical dependencies), you can use external IDs to reference non-existent (not imported yet) content:

  1. Define external IDs for all content items and assets you want to import in advance.
  2. When referencing another content item or asset, use its external ID.
  3. Import your content using the upsert methods with external ID. The system will resolve all references.

This way, you can import your content in any order and run the import process repeatedly to keep your project up to date. In the example below, we import an asset and a content item that uses it:

// Upserts an asset, assuming you already have the fileResult reference to the uploaded file
AssetUpsertModel asset = new AssetUpsertModel
{
    FileReference = fileResult
};

string assetExternalId = "Ext-Asset-123-png";
AssetModel assetResponse = await client.UpsertAssetByExternalIdAsync(assetExternalId, asset);

// Upserts a content item
ContentItemUpsertModel item = new ContentItemUpsertModel
{
    Name = "Brno",
    Type = ContentTypeIdentifier.ByCodename("cafe")
};

string itemExternalId = "Ext-Item-456-Brno";
ContentItemModel itemResponse = await client.UpsertContentItemByExternalIdAsync(itemExternalId, item);

// Upsert a language variant which references the asset using external ID
CafeModel stronglyTypedElements = new CafeModel
{
    Picture = new [] { AssetIdentifier.ByExternalId(assetExternalId) },
    City = "Brno",
    Country = "Czech Republic"
};

ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByExternalId(itemExternalId);
LanguageIdentifier languageIdentifier = LanguageIdentifier.ByCodename("en-US");
ContentItemVariantIdentifier identifier = new ContentItemVariantIdentifier(itemIdentifier, languageIdentifier);

ContentItemVariantModel<CafeModel> variantResponse = await client.UpsertContentItemVariantAsync<CafeModel>(identifier, stronglyTypedElements);

Content item methods

Upserting a content item by external ID

// Defines a content item to upsert
ContentItemUpsertModel item = new ContentItemUpsertModel
{
    Name = "New or updated name",
    Type = ContentTypeIdentifier.ByCodename("cafe"),
    SitemapLocations = new[] { SitemapNodeIdentifier.ByCodename("cafes") }
};

string itemExternalId = "Ext-Item-456-Brno";

// Upserts a content item by external ID
ContentItemModel response = await client.UpsertContentItemByExternalIdAsync(itemExternalId, item);

Adding a content item

// Defines a content item to add
ContentItemCreateModel item = new ContentItemCreateModel
{
    Name = "Brno",
    Type = ContentTypeIdentifier.ByCodename("cafe"),
    SitemapLocations = new[] { SitemapNodeIdentifier.ByCodename("cafes") }
};

// Creates a content item
ContentItemModel response = await client.CreateContentItemAsync(item);

Viewing a content item

ContentItemIdentifier identifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));

// Retrieves a content item
ContentItemModel response = await client.GetContentItemAsync(identifier);

Listing content items

// Retrieves a list of content items
ListingResponseModel<ContentItemModel> response = await client.ListContentItemsAsync();

while (true)
{
    foreach (var item in response)
    {
        // use your content item
    }

    if (!response.HasNextPage())
    {
        break;
    }

    response = await response.GetNextPage();
}

Updating a content item

ContentItemIdentifier identifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));

// Defines new properties of a content item
ContentItemUpdateModel item = new ContentItemUpdateModel
{
    Name = "New name",
    SitemapLocations = new[] {
        SitemapNodeIdentifier.ByCodename("cafes"),
        SitemapNodeIdentifier.ByCodename("europe")
    }
};

// Updates a content item
ContentItemModel reponse = await client.UpdateContentItemAsync(identifier, item);

Deleting a content item

ContentItemIdentifier identifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));

// Deletes a content item
client.DeleteContentItemAsync(identifier);

Language variant methods

Upserting a language variant

// Defines the elements to update
CafeModel stronglyTypedElements = new CafeModel
{
    Street = "Nove Sady 25",
    City = "Brno",
    Country = "Czech Republic"
};

ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");

LanguageIdentifier languageIdentifier = LanguageIdentifier.ByCodename("en-US");
// LanguageIdentifier languageIdentifier = LanguageIdentifier.ById(Guid.Parse("00000000-0000-0000-0000-000000000000"));

// Combines item and language identifiers into one
ContentItemVariantIdentifier identifier = new ContentItemVariantIdentifier(itemIdentifier, languageIdentifier);
// Upserts a language variant of a content item
ContentItemVariantModel<CafeModel> response = await client.UpsertContentItemVariantAsync<CafeModel>(identifier, stronglyTypedElements);

Viewing a language variant

ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");

LanguageIdentifier languageIdentifier = LanguageIdentifier.ByCodename("en-US");
// LanguageIdentifier languageIdentifier = LanguageIdentifier.ById(Guid.Parse("00000000-0000-0000-0000-000000000000"));

// Combines item and language identifiers into one
ContentItemVariantIdentifier identifier = new ContentItemVariantIdentifier(itemIdentifier, languageIdentifier);
// Retrieves a language variant of a content item
ContentItemVariantModel<CafeModel> response = await client.GetContentItemVariantAsync<CafeModel>(identifier);

Listing language variants

ContentItemIdentifier identifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier identifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79"));
// ContentItemIdentifier identifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");

// Retrieves language variants of a content item
IEnumerable<ContentItemVariantModel<CafeModel>> response = await client.ListContentItemVariantsAsync<CafeModel>(identifier);

Deleting a language variant

ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByCodename("brno");
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ById(Guid.Parse("8ceeb2d8-9676-48ae-887d-47ccb0f54a79")));
// ContentItemIdentifier itemIdentifier = ContentItemIdentifier.ByExternalId("Ext-Item-456-Brno");

LanguageIdentifier languageIdentifier = LanguageIdentifier.ByCodename("en-US");
// LanguageIdentifier languageIdentifier = LanguageIdentifier.ById(Guid.Parse("00000000-0000-0000-0000-000000000000"));

// Combines item and language identifiers into one
ContentItemVariantIdentifier identifier = new ContentItemVariantIdentifier(itemIdentifier, languageIdentifier);
// Deletes a language variant of a content item
await client.DeleteContentItemVariantAsync(identifier);

Asset methods

Uploading a file

Upload a file to Kentico Cloud.

MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes("Hello world from CM API .NET SDK"));
string fileName = "Hello.txt";
string contentType = "text/plain";

// Returns a reference that you can later use to create an asset
FileReference fileResult = await client.UploadFileAsync(new FileContentSource(stream, fileName, contentType));

Upserting an asset using external ID

Update or create an asset using a fileResult reference to a previously uploaded file. You can specify an asset description for each language in your Kentico Cloud project. Specifying title of a new asset is optional. Use the asset title to better identify and filter your assets in the UI.

AssetDescription assetDescription = new AssetDescription
{
    Description = "Description of the asset in English Language",
    Language = LanguageIdentifier.ByCodename("en-US")
};
IEnumerable<AssetDescription> descriptions = new [] { assetDescription };

// Title of a new asset
string title = "Asset title";

// Defines the asset to upsert
AssetUpsertModel asset = new AssetUpsertModel
{
    FileReference = fileResult,
    Descriptions = descriptions,
    Title = title
};

string externalId = "Ext-Asset-123-png";

// Upserts an asset by external ID
AssetModel response = await client.UpsertAssetByExternalIdAsync(externalId, asset);

Uploading an asset from a file system in a single step

Import the asset file and its descriptions using a single method. Specifying title of an asset is optional. You can use the asset title to better identify and filter your assets in the UI.

AssetDescription assetDescription = new AssetDescription
{
    Description = "Description of the asset in English Language",
    Language = LanguageIdentifier.ByCodename("en-US")
};

IEnumerable<AssetDescription> descriptions = new [] { assetDescription };

// Title of a new asset
string title = "Asset title";

// Defines the asset to update
AssetUpdateModel asset = new AssetUpdateModel
{
    Descriptions = descriptions,
    Title = title
};

string filePath = "‪C:\Users\Kentico\Desktop\puppies.png";
string contentType = "image/png";

// Creates a new asset using the given file and its descriptions
AssetModel response = await client.CreateAssetAsync(new FileContentSource(filePath, contentType), asset);

Viewing an asset

AssetIdentifier identifier = AssetIdentifier.ByExternalId("Ext-Asset-123-png");
// AssetIdentifier identifier = AssetIdentifier.ById(Guid.Parse("fcbb12e6-66a3-4672-85d9-d502d16b8d9c"));

// Retrieves an asset
AssetModel response = await client.GetAssetAsync(identifier);

Listing assets

// Retrieves a list of all assets
ListingResponseModel<AssetModel> response = await client.ListAssetsAsync();

while (true)
{
    foreach (var asset in response)
    {
        // use your asset
    }

    if (!response.HasNextPage())
    {
        break;
    }

    response = await response.GetNextPage();
}

Deleting an asset

AssetIdentifier identifier = AssetIdentifier.ByExternalId("Ext-Asset-123-png");
// AssetIdentifier identifier = AssetIdentifier.ById(Guid.Parse("fcbb12e6-66a3-4672-85d9-d502d16b8d9c"));

// Deletes an asset
client.DeleteAssetAsync(identifier);

Helper Methods

Methods for building links to content items and their elements in Kentico Cloud. Available as a separate NuGet package.

Getting an edit link for a content item

var options = new ContentManagementHelpersOptions
{
    ProjectId = "bb6882a0-3088-405c-a6ac-4a0da46810b0",
};

string itemId = "8ceeb2d8-9676-48ae-887d-47ccb0f54a79";
string languageCodename = "en-US";

var linkBuilder = new EditLinkBuilder(options);
var result = linkBuilder.BuildEditItemUrl(languageCodename, itemId);

// Result is "https://app.kenticocloud.com/goto/edit-item/project/bb6882a0-3088-405c-a6ac-4a0da46810b0/
// variant-codename/en-US/item/8ceeb2d8-9676-48ae-887d-47ccb0f54a79"

Getting an edit link for a specific content element

var options = new ContentManagementHelpersOptions
{
    ProjectId = "bb6882a0-3088-405c-a6ac-4a0da46810b0",
};

string itemId = "8ceeb2d8-9676-48ae-887d-47ccb0f54a79";
string languageCodename = "en-US";
var elementIdentifier = new ElementIdentifier(itemId, "single-Element-Codename");

var linkBuilder = new EditLinkBuilder(options);
var result = linkBuilder.BuildEditItemUrl(languageCodename, elementIdentifier);

// Result is "https://app.kenticocloud.com/goto/edit-item/project/bb6882a0-3088-405c-a6ac-4a0da46810b0/
// variant-codename/en-US/item/8ceeb2d8-9676-48ae-887d-47ccb0f54a79/element/single-Element-Codename"

Getting an edit link for multiple content elements

var options = new ContentManagementHelpersOptions
{
    ProjectId = "bb6882a0-3088-405c-a6ac-4a0da46810b0",
};

string languageCodename = "en-US";
var elements = new ElementIdentifier[]
{
    new ElementIdentifier("76c06b74-bae9-4732-b629-1a59395e893d", "some-Element-Codename-1"),
    new ElementIdentifier("326c63aa-ae71-40b7-a6a8-56455b0b9751", "some-Element-Codename-2"),
    new ElementIdentifier("ffcd0436-8274-40ee-aaae-86fee1966fce", "some-Element-Codename-3"),
    new ElementIdentifier("d31d27cf-ddf6-4040-ab67-2f70edc0d46b", "some-Element-Codename-4"),
};

var linkBuilder = new EditLinkBuilder(options);
var result = linkBuilder.BuildEditItemUrl(languageCodename, elements);

// Result is "https://app.kenticocloud.com/goto/edit-item/"
//    project/bb6882a0-3088-405c-a6ac-4a0da46810b0/variant-codename/en-US/
//    item/76c06b74-bae9-4732-b629-1a59395e893d/element/some-Element-Codename-1/
//    item/326c63aa-ae71-40b7-a6a8-56455b0b9751/element/some-Element-Codename-2/
//    item/ffcd0436-8274-40ee-aaae-86fee1966fce/element/some-Element-Codename-3/
//    item/d31d27cf-ddf6-4040-ab67-2f70edc0d46b/element/some-Element-Codename-4"

Further information

For more developer resources, visit the Kentico Cloud Developer Hub at https://developer.kenticocloud.com.

Building the sources

Prerequisites:

Required: .NET Core SDK.

Optional:

Feedback & Contributing

Check out the contributing page to see the best places to file issues, start discussions, and begin contributing.

Analytics