Appearance
Are you an LLM? You can read better optimized documentation at /api_reference/models.md for this page in Markdown format
Models
Overview
This document provides a comprehensive technical reference for the data models used in TheExampleApp. These models are C# classes that serve as the application's representation of content stored in the Contentful headless CMS. They are fundamental to how the application fetches, processes, and renders data.
The mapping between Contentful content types and these C# classes is managed by the contentful.aspnetcore SDK. Each model class corresponds to a specific Contentful content type, and its properties map to the fields of that content type. This approach provides strong typing and IntelliSense support, significantly improving developer experience and reducing runtime errors.
For a higher-level overview of how these models fit into the data-fetching pipeline, please refer to the Contentful Integration documentation.
BasePageModel
The BasePageModel is a base class that provides common functionality for all Razor Page models in the application. It inherits from ASP.NET Core's PageModel and is responsible for initializing the Contentful client.
csharp
// TheExampleApp/Models/BasePageModel.cs
using Contentful.Core;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TheExampleApp.Configuration;
namespace TheExampleApp.Models
{
/// <summary>
/// Base model for all other models containing some common configuration.
/// </summary>
public class BasePageModel : PageModel
{
/// <summary>
/// The client used to communicate with the Contentful API.
/// </summary>
protected readonly IContentfulClient _client;
/// <summary>
/// Initializes a new BasePageModel.
/// </summary>
/// <param name="client">The client used to communicate with the Contentful API.</param>
public BasePageModel(IContentfulClient client)
{
_client = client;
_client.ContentTypeResolver = new ModulesResolver();
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Key Implementation Details
- Dependency Injection: The
IContentfulClientis injected via the constructor, adhering to standard ASP.NET Core DI patterns. - ContentTypeResolver: The most critical function of this class is setting the
_client.ContentTypeResolver. The customModulesResolveris essential for handling polymorphic relationships, specifically theList<ILessonModule>in theLessonmodel. It inspects the Contentful content type ID of a linked entry and resolves it to the correct concrete C# class (e.g.,LessonCopy,LessonImage). Without this, the SDK would not know which class to instantiate for items in theModulescollection.
Course
The Course model represents a course, which is a central content type in the application. It aggregates various pieces of information, including descriptive text, metadata, and collections of related Lesson and Category entries.
csharp
// TheExampleApp/Models/Course.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contentful.Core.Models;
namespace TheExampleApp.Models
{
/// <summary>
/// Represents a course in the application.
/// </summary>
public class Course
{
/// <summary>
/// The system defined meta data properties.
/// </summary>
public SystemProperties Sys { get; set; }
/// <summary>
/// The title of the course.
/// </summary>
public string Title { get; set; }
/// <summary>
/// The slug for the course.
/// </summary>
public string Slug { get; set; }
/// <summary>
/// The image for the course.
/// </summary>
public Asset Image { get; set; }
/// <summary>
/// The short description of the course.
/// </summary>
public string ShortDescription { get; set; }
/// <summary>
/// The description of the course.
/// </summary>
public string Description { get; set; }
/// <summary>
/// The duration of the course in minutes.
/// </summary>
public int Duration { get; set; }
/// <summary>
/// The skill level required to complete the course.
/// </summary>
public string SkillLevel { get; set; }
/// <summary>
/// The lessons this course contain.
/// </summary>
public List<Lesson> Lessons { get; set; }
/// <summary>
/// The categories this course belongs to.
/// </summary>
public List<Category> Categories { get; set; }
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Properties
Image: AnAssetobject from the Contentful SDK, representing the course's hero image. TheAsset.File.Urlproperty will contain the URL to the image file.Description: A long-form text field. Given the inclusion of theMarkdiglibrary, this field likely contains Markdown content that must be parsed before rendering.Duration: An integer representing the duration of the course in minutes.Lessons: AList<Lesson>representing a one-to-many relationship. This contains all lessons that are part of the course.Categories: AList<Category>representing a many-to-many relationship, used for organizing and filtering courses.
Lesson
The Lesson model represents an individual lesson within a Course. Its structure is notable for its use of a modular content pattern.
csharp
// TheExampleApp/Models/Lesson.cs
using System.Collections.Generic;
using Contentful.Core.Models;
namespace TheExampleApp.Models
{
public class Lesson
{
public SystemProperties Sys { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public List<ILessonModule> Modules { get; set; }
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Key Implementation Details
ModulesProperty: TheList<ILessonModule> Modulesproperty is the core feature of this model. It is a collection of interface types, allowing a lesson to be composed of various different content modules (e.g., text blocks, images, code snippets). This polymorphic relationship is enabled by theModulesResolver(seeBasePageModel). This design provides maximum flexibility for content authors to build diverse lesson layouts without requiring code changes.
Category
The Category model is a simple taxonomy object used to group and classify Course entries.
csharp
// TheExampleApp/Models/Category.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contentful.Core.Models;
namespace TheExampleApp.Models
{
/// <summary>
/// Represents a category.
/// </summary>
public class Category
{
/// <summary>
/// The system defined meta data properties.
/// </summary>
public SystemProperties Sys { get; set; }
/// <summary>
/// The title of the category.
/// </summary>
public string Title { get; set; }
/// <summary>
/// The slug for the category.
/// </summary>
public string Slug { get; set; }
/// <summary>
/// The description of the category.
/// </summary>
public string Description { get; set; }
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
IModule
The IModule interfaces are a key architectural pattern for creating a flexible, component-based content system. They serve as marker interfaces to categorize different types of reusable content blocks (modules).
csharp
// TheExampleApp/Models/IModule.cs
using Contentful.Core.Models;
namespace TheExampleApp.Models
{
/// <summary>
/// Interface to mark which classes can be used as modules.
/// </summary>
public interface IModule
{
SystemProperties Sys { get; set; }
}
/// <summary>
/// Interface to mark lesson modules.
/// </summary>
public interface ILessonModule : IModule
{
}
/// <summary>
/// Interface to mark layout modules.
/// </summary>
public interface ILayoutModule : IModule
{
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Design Rationale
IModule: The base interface requires only aSystemProperties Sysproperty. This is the minimum requirement for any class that maps to a Contentful entry, asSys.ContentType.SystemProperties.Idis used by theContentTypeResolverto identify the module type.ILessonModule&ILayoutModule: These derived interfaces act as "markers." They allow the system to differentiate between modules intended for different contexts. For example, aLessoncan only containILessonModules, while a generic page layout might only useILayoutModules. This enforces content modeling rules at the application level.
Layout modules
Layout modules are concrete classes that implement the ILayoutModule interface. They are reusable content blocks intended for building general page layouts, such as a home page or a landing page.
Examples include:
LayoutCopy: A block of rich text.LayoutHeroImage: A large hero banner with a title and call-to-action.LayoutHighlightedCourse: A card that features a specific course.
The concrete implementations for these models are defined in separate files. For detailed information on their properties and usage, see the Layout Modules documentation.
Lesson modules
Lesson modules are concrete classes that implement the ILessonModule interface. They are the building blocks for the content of a Lesson.
Examples include:
LessonCopy: A block of instructional text, likely supporting Markdown.LessonImage: An image with an optional caption.LessonCodeSnippets: A specialized module for displaying formatted code with syntax highlighting.
The concrete implementations for these models are defined in separate files. For detailed information on their properties and usage, see the Lesson Modules documentation.
Property reference
The following table describes properties that are common across multiple models.
| Property | Type | Source | Description |
|---|---|---|---|
Sys | SystemProperties | Contentful.Core.Models | Contains system-managed metadata for a Contentful entry, including its unique ID (Sys.Id), version, creation/update timestamps, and content type (Sys.ContentType). Essential for debugging and content type resolution. |
Title | string | Contentful Field | A standard short text field, typically used for headings and labels. |
Slug | string | Contentful Field | A URL-friendly string used to generate unique, human-readable URLs for content entries (e.g., /courses/{slug}). |
Description | string | Contentful Field | A long text field. In this application, it is expected to contain Markdown, which is processed by the Markdig library before rendering. |
Image | Asset | Contentful.Core.Models | Represents a link to a media file in the Contentful space. The actual file URL is accessed via Image.File.Url. |
Model relationships
The models are interconnected, forming a content graph that defines the application's structure. Understanding these relationships is crucial for querying and rendering data correctly.
Course <> Lesson (One-to-Many)
- A
Coursecontains aList<Lesson>. This is a direct parent-child relationship. When aCourseis fetched, its linkedLessonentries can be included in the same API call to avoid extra requests.
- A
Course <> Category (Many-to-Many)
- A
Coursecontains aList<Category>, and aCategorycan be associated with multiple courses. This relationship is managed in Contentful via a multi-reference field.
- A
Lesson <> ILessonModule (Polymorphic One-to-Many)
- This is the most complex and powerful relationship. A
Lessoncontains aList<ILessonModule>. Each item in this list can be a different concrete type (e.g.,LessonCopy,LessonImage). This allows for highly flexible and dynamic lesson content. - Technical Implementation: This relationship relies on three key components:
- A "Links" field in Contentful on the Lesson content type that can reference multiple different module content types.
- The
ILessonModulemarker interface in the C# code. - The
ModulesResolverclass, which maps Contentful content type IDs to the concrete C# model classes at deserialization time.
- This is the most complex and powerful relationship. A
For more context on the overall data flow, refer to the Contentful Integration architecture document.