Building your first .NET Core app
This tutorial will show you how to create an ASP.NET Core MVC app from scratch and use it to display content from your Kentico Kontent project. If you're new to ASP.NET Core MVC, you might want to take the Microsoft Getting started with ASP.NET Core MVCOpens in a new window tutorial first.
New to Kentico Kontent?
If you're starting with Kentico Kontent, we suggest you begin with the Hello World tutorial, in which you'll learn the basics of creating content.
Table of contents
You'll use the Kentico Kontent boilerplateOpens in a new window (in other words, a template for new applications with a few basic features built on top) and customize it to suit your needs. The boilerplate includes features such as simple fixed-time caching, the Delivery .NET SDK (for fetching content from your Kentico Kontent project), 404 error handling, logging, a sitemap.xml generator, and more.
Requirements
Make sure you have the following installed:
- .NET Core SDK 2.0.0Opens in a new window or newer
- An IDE (such as Visual Studio 2017Opens in a new window) or the text editor of your choice
Preparing the boilerplate
Open a command line and register the ASP.NET Core MVC with Kentico Kontent custom template in your .NET Core templates by running the following command.
dotnet new --install "Kentico.Kontent.Boilerplate::*"dotnet new --install "Kentico.Kontent.Boilerplate::*"
Now you can initialize a new app based on new .NET Core template.
dotnet new kentico-kontent-mvc --name "MyWebsite"dotnet new kentico-kontent-mvc --name "MyWebsite"
Your new web app is ready. Navigate to its folder and run it.
cd .\MyWebsite dotnet runcd .\MyWebsite dotnet run
Your app will start and be available at http://localhost:5000
. Open the address in your browser to view it.

How the boilerplate will look on first run
Connecting the app to your project
Right now the app fetches content from the default Sample Project and displays a preview of 3 articles.
To connect the app to your own project:
- In Kentico Kontent, choose Project settings from the app menu.
- Under Development, choose API keys.
- In the Delivery API box, click Copy to clipboard to copy the Project ID.
- In the app folder, open the
appsettings.json
file. - Replace the value of the
ProjectId
key with the ID of your project. - Save the changes.
When you now run the app again and open http://localhost:5000
in your browser, the app will work with data from the specified project.
Adding classes for your content types
To make further app development easier, we recommend using the Kentico Kontent model generator for .NET to create strongly-typed models representing your content types. To learn more about this approach in general, see Using strongly typed models.
Sample models
By default, the boilerplate comes with a single model describing the structure of an Article content type – you can find the model in the \Models\ContentTypes\
folder.
The Article model is referenced as an example in multiple locations across the app:
\Controllers\HomeController.cs
\Controllers\SiteMapController.cs
\Views\Home\Index.cshtml
\Views\Shared\DisplayTemplates\Article.cshtml
You can adjust these references later when you customize the app.
Your project will likely have other content types with different structures than the included sample model. This means you can safely overwrite the contents of the \Models\ContentTypes\
folder with your own models.
1. Generating models
First, in your command line, run the following command to install the model generator tool for your app.
# Installs the Kontent model generator tool locally into the app's folder dotnet tool restore# Installs the Kontent model generator tool locally into the app's folder dotnet tool restore
The model generator is now available as a KontentModelGenerator
tool.
Next, in your command line, use the dotnet tool run KontentModelGenerator
command with the following parameters:
--projectid
– specifies the ID of your Kentico Kontent project.--withtypeprovider
– tells the generator to create theCustomTypeProvider
class to support runtime type resolutionOpens in a new window.--generatepartials
– tells the generator to create partial classes for easier customization.--structuredmodel
– tells the generator to type rich text elements asIRichTextContentobjects
instead of strings.--outputdir
– specifies where to store the generated models.--namespace
– specifies the namespace of the generated models.
# Note: This overwrites existing files in the .\Models\ContentTypes folder dotnet tool run KontentModelGenerator --projectid "<YOUR_PROJECT_ID>" --withtypeprovider --structuredmodel --outputdir ".\Models\ContentTypes" --namespace "MyWebsite.Models" --generatepartials# Note: This overwrites existing files in the .\Models\ContentTypes folder dotnet tool run KontentModelGenerator --projectid "<YOUR_PROJECT_ID>" --withtypeprovider --structuredmodel --outputdir ".\Models\ContentTypes" --namespace "MyWebsite.Models" --generatepartials
The models are generated as partial classes. For each content type, the generator creates two files, one with the suffix .Generated
and another with room for your code. This means you can extend the models in separate files and re-generate them in the future without losing your custom code. If you'd like to learn more about the data types used for individual content elements, see Working with strongly typed modelsOpens in a new window.
2. Mapping retrieved content to your models
Now, when you fetch content items from your project, you can map the returned data to a specific model.
// Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using Kentico.Kontent.Delivery; // Initializes a content delivery client IDeliveryClient client = DeliveryClientBuilder .WithProjectId("<YOUR_PROJECT_ID>") .Build(); // Retrieves 3 articles ordered by their post date DeliveryItemListingResponse<Article> response = await client.GetItemsAsync<Article>( new EqualsFilter("system.type", "article"), new LimitParameter(3), new OrderParameter("elements.post_date", SortOrder.Descending) ); // Sends the strongly-typed content items to a View return View(response.Items)// Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using Kentico.Kontent.Delivery; // Initializes a content delivery client IDeliveryClient client = DeliveryClientBuilder .WithProjectId("<YOUR_PROJECT_ID>") .Build(); // Retrieves 3 articles ordered by their post date DeliveryItemListingResponse<Article> response = await client.GetItemsAsync<Article>( new EqualsFilter("system.type", "article"), new LimitParameter(3), new OrderParameter("elements.post_date", SortOrder.Descending) ); // Sends the strongly-typed content items to a View return View(response.Items)
You can find the code in the HomeController
controller.
Mapping to your models
Use the same approach to map your content to the models of your content types. Make sure you adjust the following when retrieving content:
- Replace instances of
Article
with the name of the class representing your content type. - Replace
article
in theEqualsFilter
parameter with the codename of your content type. - Replace the value of the
OrderParameter
so that the API orders the results by values in existing elements or system attributes.
If you want to learn more about content filtering in .NET, check out Getting to Know the .NET SDK Delivery API FiltersOpens in a new window.
3. Displaying your content
After that, you can access any of the content type's elements (as model properties) in the app's Views.
@using MyWebsite.Helpers.Extensions @model Article <div class="body"> <h2>@Model.Title</h2> <!-- Generates an IMG element for the image using a helper method. --> @Html.AssetImage(@Model.TeaserImage.First(), title: @Model.TeaserImage.First().Name, cssClass: "img-responsive", sizes: new ResponsiveImageSizes(300) .WithMediaCondition(new MediaCondition { MinWidth = 330, MaxWidth = 768, ImageWidth = 689 }))> @Model.Summary </div>@using MyWebsite.Helpers.Extensions @model Article <div class="body"> <h2>@Model.Title</h2> <!-- Generates an IMG element for the image using a helper method. --> @Html.AssetImage(@Model.TeaserImage.First(), title: @Model.TeaserImage.First().Name, cssClass: "img-responsive", sizes: new ResponsiveImageSizes(300) .WithMediaCondition(new MediaCondition { MinWidth = 330, MaxWidth = 768, ImageWidth = 689 }))> @Model.Summary </div>
If you're using a different model, be sure to change the model declaration and individual properties.
Rendering rich text elements
To render rich text elements, use the Html.DisplayFor
helper method in your Views.
@* Renders content of a rich text element (BodyCopy in an article) *@ @Html.DisplayFor(model => model.BodyCopy)@* Renders content of a rich text element (BodyCopy in an article) *@ @Html.DisplayFor(model => model.BodyCopy)
Right now, individual blocks of content in rich text elements will be rendered using their default HTML representation, matching the content returned by the Delivery API. But you can also write your own representations of rich content.
Rendering rich content
To customize the way your app renders components, content items and inline images, you need to provide display templates for them:
- Components and content items – display template named
<ModelName>.cshtml
where theModelName
refers to the content type of the content item or component, for example,Tweet.cshtml
. - (Optional) Inline images – display template named InlineImage.cshtml.
For a more in-depth example, see Dealing with structure in rich text.
Resolving URLs
If your rich text elements contain links to other content items, you need to tell your app how to form correct URLs.
To do this, open the Resolvers\CustomContentLinkUrlResolver.cs
file in your app and add implementation to the following methods:
ResolveLinkUrl
– used when the linked content item is available.ResolveBrokenLinkUrl
– used when the linked content item is not available.
Note that both methods must return strings.
See the example below and add more logic based on your content types.
public string ResolveLinkUrl(ContentLink link) { // Resolves links pointing to Article content items if (link.ContentTypeCodename.Equals(Article.Codename)) { return $"/articles/{link.UrlSlug}"; } // Add the rest of the resolver logic } public string ResolveBrokenLinkUrl() { // Resolves URLs to unavailable content items return "/Error/404"; }public string ResolveLinkUrl(ContentLink link) { // Resolves links pointing to Article content items if (link.ContentTypeCodename.Equals(Article.Codename)) { return $"/articles/{link.UrlSlug}"; } // Add the rest of the resolver logic } public string ResolveBrokenLinkUrl() { // Resolves URLs to unavailable content items return "/Error/404"; }
If you want to learn more about the way these resolvers work, see Resolving links to content itemsOpens in a new window.
Configuring the app
The boilerplate also includes a set of pre-configured features such as error handling, fixed-time caching, sitemap.xml generator, and others. You can configure most of these features in the Startup.cs
file.
Error handling
When you run the app locally on your machine without specifying any environment-specific launch profileOpens in a new window, the app will use a development profile. This means that if your app encounters an exception, it will be logged to the console and displayed directly in your browser.
In a production environment (that is when the app is run with a production profile), all errors are still logged, but a custom error page is displayed instead of the stack trace.
If you'd like to tweak the error handling and relevant error pages, see the following:
- The Configure method in the Startup class – specifies app behavior in different environments.
- The ErrorController controller – specifies what pages to display for specific HTTP status codes such as 404 Not Found.
- The views in the
Views\Error
folder – contain pages that are displayed when an error occurs in a production environment.
Caching
To use fewer Content API calls, the app employs a fixed-time caching mechanism and stores the retrieved content in its memory for 5 minutes. Without any caching, you would be making requests to the Delivery API with each page load. You can set a different time by changing the CacheTimeoutSeconds
key in the appsettings.json
file. To learn more about caching with Kentico Kontent, see Improving performance with caching.
What's next?
The basic skeleton of your new app is now ready. We recommend you use it as a starting point and add more functionality where needed.
For example, you might find inspiration in the following:
- Our Sample .NET MVC application – includes examples of View Models and Display Templates.
- Combine your app with GraphQL using the Apollo boilerplateOpens in a new window.
- Learn about the ways to filter and sort the content you retrieve from your project.