Building ASP.NET core applications with Contentful
This tutorial will show you how to setup the Contentful SDK for an ASP.NET Core application and how to access your content.
Pre-requisites
This tutorial assumes you understand the basic Contentful data model and that you have read and understand the getting started tutorial for the .Net SDK.
Contentful.AspNetCore is built on .NET Core and targets .NET Standard 2.0. The SDK is cross-platform and runs on Linux, macOS, and Windows.
Installation
Add the package to your ASP.NET Core solution using the NuGet package manager by running the following command in your NuGet package manager console.
Install-Package contentful.aspnetcore
Or running the following with the .NET CLI.
dotnet add package contentful.aspnetcore
contentful.csharp
SDK but includes features specifically for ASP.NET Core.
Configuration
The Contentful.AspNetCore package implements the options pattern and the simplest way to configure your space id and access token is by using an appsettings.json file. Add the code below, but add your own values.
"ContentfulOptions": {
"DeliveryApiKey": "<access_token>",
"ManagementApiKey": "<cma_access_token>",
"PreviewApiKey": "<preview_access_token>",
"SpaceId": "<space_id>",
"UsePreviewApi": false,
"MaxNumberOfRateLimitRetries": 0
}
You can override each separate option with environment specific config, environment variables or by any other
Microsoft.Extensions.Configuration.IConfigurationSource
. You can even implement your own.
Register services
Next, register the services that will use the configuration settings in your Startup.cs
class. Add a using statement for
Contentful.AspNetCore
and in the ConfigureServices
method add the following line.
services.AddContentful(Configuration);
Your first request
Once you have configured everything, you can now leverage the dependency injection of your ASP.NET Core application to retrieve the IContentfulClient
or IContentfulManagementClient
in your classes. Here's an example for a controller.
public class SampleController : Controller {
private readonly IContentfulClient _client;
public SampleController(IContentfulClient client)
{
_client = client;
}
}
By using constructor injection you can automatically retrieve an instance of IContentfulClient
and use this in your actions to retrieve content.
public async Task<IActionResult> Index() {
var products = _client.GetEntries<Product>();
}
For more information on how to retrieve content using the IContentfulClient
and IContentfulManagementClient
refer to our CDA tutorial and CMA tutorial respectively.
Working with assets and the image API
A new feature of ASP.NET core is taghelpers. In the ASP.NET core SDK, there are two taghelpers that you can use when working with assets.
If you have an asset stored in Contentful and wish to output an anchor tag to that asset you can use the ContentfulAssetTagHelper
. On the anchor tag add an asset_id
attribute and the taghelper will automatically retrieve it from Contentful and add it to the href
attribute.
<a asset-id="<asset_id>">link to asset</a>
If you want to retrieve the asset from a specific locale you can add the locale
attribute.
<a asset-id="<asset_id>" locale="sv-SE">link to Swedish asset</a>
If the asset is an image you probably want to output an img
tag instead of an anchor and can use the ContentfulImageTageHelper
.
<contentful-image asset-id="<asset_id>" />
If you have the URL to the image available you can save a request by using the URL property instead.
<contentful-image url="<full_asset_file_path>" />
There are other attributes you can set that will use the Contentful Image API in the background.
<contentful-image url="<full_asset_file_path>" width="50" height="50" format="Png" resize-behaviour="Pad" background-color="#cc0000" image-focus-area="Face" corner-radius="10" />
These all correspond to similar values in our image API and will set the src
attribute of the img
correctly.
- The
width
andheight
attributes will set the width and height of the image and resize it accordingly. - The
format
attribute lets you select if you wish your image to be of a specific format, available values arePng
,Jpg
orWebp
. - The
resize-behaviour
attribute lets you specify how the image should be resized to fit within the constraints of the width and height.- Available values are
Pad
,Crop
,Fill
,Thumb
andScale
.
- Available values are
- The
background-color
attribute lets you specify what color the padding of the image should be when using thePad
resize behavior.- You can specify your value in using RGB or hash-notation. For example
rgb:000080
or#000080
.
- You can specify your value in using RGB or hash-notation. For example
- The
image-focus-area
attribute lets you specify which part of an image to focus on when doing resizing. Available values areTop
,Left
,Right
,Bottom
,Top_Right
,Top_Left
,Bottom_Right
,Bottom_Left
,Face
orFaces
. - The
corner-radius
allows you to round the corner of the image by the specified radius.
There are two attributes specifically for jpeg images.
<contentful-image url="<full_asset_file_path>" jpg-quality="50" progressive-jpg="True" />
- The
jpg-quality
attribute lets you specify a number between 0 and 100 that corresponds to the quality of the outputted JPEG image. - The
progressive-jpg
attribute lets you specify whether to use progressive JPEGs or not.
The output from a contentful-image
will be a regular img
tag and every attribute added to it that is not part of the taghelper will be retained. This means that you can, for example, specify an alt text or class directly on the taghelper and the outputted image will keep it.
<contentful-image url="<full_asset_file_path>" width="50" height="50" alt="<alt_text>" />
You can also use the contentful-image
to output a srcset
for different image sizes.
<contentful-image url="<full_asset_file_path>" width="50" height="50" alt="<asset_name>" >
<contentful-source />
<contentful-source size="800w" width="800" />
</contentful-image>
Each contentful-source
can have the same properties as a contentful-image
and will generate a srcset
url with those properties. If you omit the size
attribute the width of the contentful-image
will be used. The example above would output an img
tag like this.
<img src="asset_url?w=50&h=50" alt="<alt_text>" srcset="asset_url?w=50&h=50 50w, asset_url?w=800&h=50 800w" />
Working with webhooks and middleware
Webhooks offer a clean and simple way to let Contentful notify an application when something changes with your content. A simple approach to set a webhook up would be to create a controller with an action and let Contentful call that action when something occurs.
public class WebHookController : Controller {
[HttpPost]
public IActionResult Consumer(dynamic payload) {
//Do something when the hook is triggered
return Json("All is well");
}
}
This works fine, but it can feel overly complicated to have to create a controller to be able to consume a webhook. The ASP.NET Core SDK offers another way by using a middleware component that you set up in your Startup.cs
.
Add the following to your Configure
method.
app.UseContentfulWebhooks(consumers => {
});
This injects the middleware into the pipeline. The middleware will automatically catch any incoming webhook requests from Contentful and iterate through any added consumers and execute them one at a time.
To add a consumer use the AddConsumer
method.
app.UseContentfulWebhooks(consumers => {
consumers.AddConsumer<Entry<dynamic>>("<webhook-name>", "<topic-type>", "<topic-action>", (s) =>
{
//This is the consumer method
return null;
}
);
});
Each call to AddConsumer
takes at least 4 parameters:
- The webhook name which is the name of the webhook you specified in Contentful.
- The topic type which is
Entry
,Asset
orContentType
. - The topic action which is
create
,save
,auto_save
,archive
,unarchive
,publish
,unpublish
ordelete
. For any of the values, you can pass in"*"
as a wildcard. Func<T, object>
where you specifyT
as part of the method signature. This is the actual consumer, the code that will be triggered.
If you, for example, want to add a consumer for a webhook triggered every time an entry is created, you add a consumer like the below.
app.UseContentfulWebhooks(consumers => {
consumers.AddConsumer<dynamic>("*", "Entry", "create", (s) =>
{
//Code to notify someone a new entry has been created
//Return an object that will be serialized into Json and viewable in the Contentful web app
return new { Result = "Ok" };
}
);
});
It's valid to add multiple consumers for the same request type. They will execute in order.
app.UseContentfulWebhooks(consumers => {
consumers.AddConsumer<dynamic>("*", "Entry", "create", (s) =>
{
return new { Result = "Ok" };
}
);
consumers.AddConsumer<dynamic>("*", "Entry", "*", (s) =>
{
return new { Result = "Ok again!" };
}
);
});
You can add authorization by setting the WebhookAuthorization
property.
app.UseContentfulWebhooks(consumers => {
consumers.AddConsumer<dynamic>("*", "Entry", "create", (s) =>
{
return new { Result = "Ok" };
}
);
consumers.WebhookAuthorization = (httpcontext) => false;
});
WebhookAuthorization
is a Func<HttpContext, bool>
that you can set to any method accepting an HttpContext
and return a bool
.
app.UseContentfulWebhooks(consumers => {
consumers.WebhookAuthorization = YourAuthorizationMethod;
});
In your method, you can then inspect the HttpContext
and verify that the request is authorized. If it is, return True
, else return False
and the request will fail with a 401 error.
You can add per-consumer authorization.
app.UseContentfulWebhooks(consumers => {
consumers.AddConsumer<dynamic>("*", "Entry", "create", (s) =>
{
return new { Result = "Ok" };
},
(httpContext) => {
var authorized = false;
//Check whether the request is authorized and set the authorized variable accordingly.
return authorized;
}
);
});
This consumer authorization is a Func<HttpContext, bool>
and the principle is the same, but this authorization will only execute for the specific consumer and not for every request.
Next steps
Not what you’re looking for? Try our FAQ.