Importing content into Kontent.ai.
The Kontent.ai team introduced the Content Management API in November 2017. This provided a mechanism to programmatically enter your pre-existing content, both saving time and reducing the errors that can happen when doing repetitive content entry.
In this post, I’ll walk through a scenario of taking some pre-existing digital content, defining a content model, and importing the data into our Kontent.ai project using the Content Management API and the .NET SDK.
The source data
For our project, we’re going to work with some data from a popular Sushi restaurant. They’re building a platform to make it easier for their customers to find out information about their menu. What we know about a dish in the menu is that we have the following information:
- Description of the dish
- Ingredients used
- Calories of the dish
- Information about ingredients that may cause an allergic response
- Category of dish (i.e. Nigiri, Sashimi, Miso etc.)
- Special dietary requirements (nut free, gluten free etc.)
- Product flags (new, improved etc.)
For each dish, we’ll have two images; one landscape and one portrait. This will enable us to deal with various layouts to suit mobile and desktop presentation.
Looking at the content we have for each dish, we can define a fairly straight forward content model.
The special dietary requirements and product flags are things that we are likely to reuse and want to filter content by. For this reasons, we’ll make them in to taxonomy terms.
The images will be two individual assets. Typically, the name is a simple piece of text, so we’ll just make this into a plain text field and reth same applies for allergens and ingredients. Calories is a number. The description will be rich text, to give the editors more flexibility.
So we’re creating a content model named Dish with the following properties:
|ImagePortrait||Asset (exactly 1)||Yes|
|Landscape image||Asset (exactly 1)||Yes|
|DishCategory||Taxonomy (Dish category)||No|
|DietaryRequirement||Taxonomy (Dietary requirement)||No|
In JSON, this each dish looks as follows:
The data source
I’m making a couple of assumptions about our data source for this. These assumptions are that:
- You have your content in a format that you are comfortable with and that you can easily deserialize. As an example, my original source is Excel, but I have created a JSON file from that content to make it easier to work with.
- Once the taxonomy terms have been created, you’ve transformed your source data such that the taxonomy terms that you’re using match those in your source data. By this i mean that the codenames line up nicely. This is simply to make the sample code easier to read, as i concentrated on things needed by the Content Management API only.
- The source data contains enough information to identify an image, but not an absolute path to the images.
We have our content model defined in Kontent.ai, so the next things we need to do is use the Kentico Kontent model generator on our project. This saves us some time by creating the C# representation of our content model. We’ve used the --contentmanagementapi flag to generate the model with additional JSON attributes, this are to allow the Content Management API to understand the structure of our class.
This then creates a class to represent our model which looks a little like this:
With the method that I am using below, it's important to make sure that the contentmanagementapi flag is set, as without it your content will not be created. Also, read up on async/await if you're not familiar with it; the content management API uses it a lot and you can create a few issues if you go wrong. How do I know? Let's just say that the support team at Kentico Kontent helped me out of a hole!
We’re now ready to cut some code and start importing. I’m writing this as a console application in Visual Studio Code, though I did initially start out using LinqPad 5 (well worth a look if you’ve not tried it).
You need the NuGet packages installed to make this work, so you may as well add this when you create the project: KenticoCloud.ContentManagement.
To import the content for each dish I went through the following steps:
- Upload the assets
- Create the content item
- Create the content variant
So my first step was to create the Assets that I wanted to assign to my content item. For each Asset uploaded, I keep note of the returned GUID, this will be used later to tie it back to the content item. Each asset consist of two parts: a collection of descriptions and a file content source. As this is just a demo, I don't have any multilingual content, so I'm just using the default language. I'm also setting the content type to image/jpg, as I know that all my images are of this type. The response ID that comes back from here is the GUID of the asset once uploaded to Kentico Kontent. So the code I'm using for the asset import is:
Creating the content item is the next step. Each content item consists of two parts, the item itself, and the language variant. As with the asset description, you need to create a language variant regardless of whether you have multilingual content. Again, you can just use the default language here. I refer to the content item in my code as a stub our variant will hold all of the juicy detail. Creating the stub is really simple - we just provide a name for the item and the content type codename. The code looks something like this:
Take note that, at the end I'm returning the codename of the newly created content item I'll be using this to specify which content item I'm adding a variant to in the next step.
When creating the content variant, we're going to add all of the fields to our content. This includes the taxonomy and the assets that we have already uploaded. This is the code I used for the variant:
There are some key points:
- In the first couple of lines, you can see that - by using the GUIDs created when uploading the assets, we can assign those assets to the content variant. As with all assets in Kentico Kontent, this needs to be an array. If you have no assets at the time of import, then you need an empty array here.
- Again, with the taxonomy, you want to pass in an empty collection if you don't have any values.
- The Description is a rich text field. This means you can't just slap some text in there and hope for the best. The content must be well formatted, which is why I've expertly wrapped a <p> tag around my content. To be super sure your things are going to be valid, you can use AngleSharp to parse your content and check validity.
Once the content item has it's values set, it's simply a case of identifying the stub with the ContentItemVariantIdentifier and pushing it up to Kentico Kontent.
The Content Management API and .NET SDK provide a simple method of importing pre-existing digital content into your project. Building application base upon Kontent.ai can be fairly quick, and this helps speed things up that little bit more.
If you're new to async/await, then you need to take care (it's well worth reading up on the subject). My advice would be to take your time to get it right to be sure of success. Only import a few items at first; if you manage toe create a content item without a variant they can be very time consuming to remove via the Kontent.ai app, you'd be well place to write something to kill all content each time you run your test:
There are a couple of good resources that I used while reading up on how to do this. It seems only fair to share: