Publishing a large number of items using the Kontent Management APIs

Akshay Sura - Partner

24 Feb 2021

Share on social media

We recently ran into a use case while importing tens of thousands of content items from an existing Monolith CMS to the new Kontent Headless CMS. We needed to publish content that was imported into Kontent. This content had already been through a workflow on the old site and was live content.

Publishing a large number of items using the Kontent Management API's was very easy once you got into it. You could do this using the REST or the .NET SDK. In this instance, I chose to do it via REST calls.

Since these are unpublished items, they will not be available via the Delivery API. We would have to first gather information on all the items we want to publish. Most of these operations that need scale are done in Azure Functions in our company. The code to gather all the resellers is shown below.

public class FeedItem { public string Codename { get; set; } public string Id { get; set; } public string Name { get; set; } }

[FunctionName("PublishResellers")] public static async void PublishResellers( [QueueTrigger("publish-reseller-project")] string index, [Queue("publish-reseller")] CloudQueue publishResellerQueue, ILogger log) { log.LogInformation("Resellers.PublishResellers:"); try { ManagementOptions options = new ManagementOptions { ApiKey = Environment.GetEnvironmentVariable("ResellerKontentApiKey"), ProjectId = Environment.GetEnvironmentVariable("ResellerKontentProjectId") }; ManagementClient client = new ManagementClient(options); var token = ""; List<FeedItem> items = new List<FeedItem>(); do { var returned = await GetItemFeed(token); if (returned != null && returned.Items.Any()) items.AddRange(returned.Items); token = returned.Pagination.Continuation_Token; } while (!string.IsNullOrEmpty(token)); if (items.Any()) { int delayInSeconds = 5; foreach (var item in items) { var cqm = new CloudQueueMessage(JsonConvert.SerializeObject(item)); await publishResellerQueue.AddMessageAsync(cqm, null, TimeSpan.FromSeconds(delayInSeconds), null, null); delayInSeconds += 1; } } log.LogInformation($"Resellers.PublishResellers: Successful "); } catch (Exception ex) { log.LogError(ex, $"Resellers.PublishResellers.Error: {ex.Message}"); } } private static async Task<ItemsFeed> GetItemFeed(string token) { using var client = new HttpClient(); client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("KontentManagementApiBaseUrl")); client.DefaultRequestHeaders.Add("User-Agent", Environment.GetEnvironmentVariable("UserAgent")); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("ResellerKontentApiKey")); if (!string.IsNullOrEmpty(token)) client.DefaultRequestHeaders.Add("x-continuation", token); var url = string.Concat("/v2/projects/", Environment.GetEnvironmentVariable("ResellerKontentProjectId"), "/items?system.type=reseller"); HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); var resp = await response.Content.ReadAsStringAsync(); var items = JsonConvert.DeserializeObject<ItemsFeed>(resp); return items; }

We are making repetitive calls to pull resellers, checking the continuation_token, and if present we set the x-continuation token for subsequent calls.

Once all the resellers are gathered, we are adding it to another queue with a delay so that we do not hit the rate limits of Kontent. When the publish queue is triggered we simply make another call to the Kontent management API to publish that item. Here is the code.

using var client = new HttpClient(); client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("KontentManagementApiBaseUrl")); client.DefaultRequestHeaders.Add("User-Agent", Environment.GetEnvironmentVariable("UserAgent")); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("ResellerKontentApiKey")); var url = string.Format("/v2/projects/{0}/items/codename/{1}/variants/codename/default/publish", Environment.GetEnvironmentVariable("ResellerKontentProjectId"), codename); StringContent content = new StringContent(string.Empty); HttpResponseMessage response = await client.PutAsync(url,content); response.EnsureSuccessStatusCode(); var resp = await response.Content.ReadAsStringAsync();

The process is very efficient and can be used when a large number of content items need to be published. You can add additional logic to control the items you are filtering out.

You can get more information on the Management API's on Kontent: https://docs.kontent.ai/reference/management-api-v2

If you have any questions, please get in touch with me. @akshaysura13 on Twitter or on Slack.

Follow us on Twitter

Follow us on LinkedIn

Follow us on YouTube

Sign up to our newsletter


Tags:

Headless CMS
Jamstack
Kontent

Share on social media

Akshay Sura

Akshay is an eight-time Sitecore MVP who has spent more than a decade working exclusively on Sitecore projects.

In addition to his work as a solution architect, Akshay is also one of the founders of SUGCON North America 2015, SUGCON India 2018 & 2019, Unofficial Sitecore Training, and the Sitecore Slack.

Akshay founded and continues to run the Sitecore Hackathon. As one of the managing partners of Konabos Consulting, Akshay will continue to work with clients to lead projects and mentor their existing teams.


Subscribe to newsletter