Appearance
Are you an LLM? You can read better optimized documentation at /api_reference/configuration.md for this page in Markdown format
Configuration classes
This document provides a detailed API reference and technical overview of the core configuration classes and services within the TheExampleApp application. These components are fundamental to managing application state, integrating with external services like Contentful, and handling user-specific context such as session data and localization.
IContentfulOptionsManager / ContentfulOptionsManager
This service provides a mechanism to dynamically manage ContentfulOptions at runtime, allowing the application to switch Contentful spaces or API keys on a per-session basis. This is a key feature for enabling live previews and multi-space configurations without altering the application's global settings.
Implementation Details
The ContentfulOptionsManager is designed to abstract the source of the Contentful configuration. It prioritizes session-based options over the application's default configuration defined in appsettings.json.
- Dependency Injection: It is registered as a scoped service and depends on
IOptions<ContentfulOptions>to access the default configuration andIHttpContextAccessorto access the current user's session. For more details on service registration, see /configuration/services.md. - Session-Based Override: The
Optionsproperty first checksHttpContext.Sessionfor a JSON-serializedContentfulOptionsobject. If one exists, it is deserialized and used for the current request. - Fallback to Defaults: If no options are found in the session, the manager falls back to the default
ContentfulOptionsinjected via theIOptionspattern. - Credential Tracking: The
IsUsingCustomCredentialsproperty provides a convenient way to check if the current session is using overridden credentials, which is useful for displaying status indicators in the UI.
The session values are typically set by the Deeplinker middleware when a user arrives with specific query parameters from the Contentful web app.
API Reference
The IContentfulOptionsManager interface exposes the following members:
| Member | Type | Description |
|---|---|---|
Options | ContentfulOptions | (Get-only) Gets the currently active ContentfulOptions, prioritizing session-based options over application defaults. |
IsUsingCustomCredentials | bool | (Get-only) Returns true if the current session is using credentials that differ from the application's default configuration. |
Code Snippet: ContentfulOptionsManager Logic
csharp
// TheExampleApp/Configuration/ContentfulOptionsManager.cs
public class ContentfulOptionsManager : IContentfulOptionsManager
{
private ContentfulOptions _options;
private readonly IHttpContextAccessor _accessor;
// ... constructor ...
/// <summary>
/// Gets the currently configured <see cref="ContentfulOptions"/> either from session, if present, or from the application configuration.
/// </summary>
public ContentfulOptions Options {
get {
var sessionString = _accessor.HttpContext.Session.GetString(nameof(ContentfulOptions));
if (!string.IsNullOrEmpty(sessionString))
{
return JsonConvert.DeserializeObject<ContentfulOptions>(sessionString);
}
return _options;
}
}
// ... IsUsingCustomCredentials implementation ...
}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
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
Deeplinker
Deeplinker is an ASP.NET Core middleware responsible for intercepting specific query string parameters to configure the user's session. Its primary purpose is to enable a seamless "deep linking" experience from the Contentful web app, allowing content editors and developers to preview content using different API environments (e.g., Preview vs. Delivery) or even different Contentful spaces entirely.
Implementation Details
The middleware inspects the incoming request's query string for a set of predefined keys.
- Middleware Pipeline: It must be registered in the
Startup.cspipeline after session middleware (app.UseSession()) but before the MVC middleware (app.UseMvc()) to ensure it can modify the session before controllers are executed. - Credential Handling: If
space_id,preview_token, anddelivery_tokenare all present, it constructs a newContentfulOptionsobject. These options are validated, and upon success, serialized to the user's session. - Validation and Redirect: If the provided credentials fail validation, the middleware serializes the validation errors and redirects the user to the
/settingspage to correct them. This prevents the application from proceeding with invalid credentials. - API Switching: The
apiparameter (e.g.,?api=cpa) allows toggling theUsePreviewApiflag without changing other credentials. - Editorial Features: The
editorial_featuresparameter toggles a session flag that can be used to enable or disable UI elements related to content editing previews.
Configuration and Usage
The middleware is added to the application pipeline using the provided extension method.
csharp
// In Startup.cs -> Configure()
// Session must be enabled before the Deeplinker middleware.
app.UseSession();
// Adds the Deeplinker middleware to the pipeline.
app.UseDeeplinks();
app.UseMvc();1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Handled Query Parameters
| Parameter | Example Value | Description |
|---|---|---|
space_id | cfexampleapi | The ID of the Contentful space to use. |
delivery_token | b4c... | The Content Delivery API (CDA) token. |
preview_token | e59... | The Content Preview API (CPA) token. |
api | cpa | Sets UsePreviewApi to true. Any other value or absence implies the Delivery API. |
editorial_features | enabled | Enables editorial feature flags in the session. disabled explicitly disables them. |
IBreadcrumbsManager / Breadcrumbs
This feature set provides automatic breadcrumb generation based on the URL path, with the ability to programmatically override labels for dynamic segments. It consists of a middleware for generation, a service for modification, and a model for data representation.
Component Breakdown
BreadcrumbsMiddleware: Automatically creates a breadcrumb trail from the request path.IBreadcrumbsManager/BreadcrumbsManager: A scoped service to modify the generated breadcrumbs within a controller or view.BreadcrumbModel: A simple class representing a single breadcrumb link. See /api_reference/models.md for more on data models.
Breadcrumbs Middleware
This middleware processes each incoming request to build a list of Breadcrumb objects.
- Workflow:
- It splits the request path into segments (e.g.,
/courses/hello-world->["courses", "hello-world"]). - It creates a root "Home" breadcrumb.
- For each path segment, it attempts to find a localized label using
IViewLocalizer. It looks for a JSON key likecoursesLabel. If not found, it uses the raw segment (with hyphens replaced by spaces). - The generated
List<Breadcrumb>is stored inHttpContext.Items["breadcrumbs"]for the duration of the request.
- It splits the request path into segments (e.g.,
- Configuration:csharp
// In Startup.cs -> Configure() app.UseBreadcrumbs();1
2
IBreadcrumbsManager / BreadcrumbsManager Service
This service allows you to refine the automatically generated breadcrumbs. It is essential for dynamic routes where a URL slug (e.g., a-course-slug) needs to be replaced with a human-readable title (e.g., "A Course Title") fetched from the database or CMS.
API Reference
| Method | Return Type | Description |
|---|---|---|
ReplaceCrumbForSlug(string slug, string label) | void | Finds a breadcrumb whose current Label matches the slug and replaces it with the new label. |
Usage Example
In a Razor Page or MVC Controller, inject IBreadcrumbsManager and use it to update the breadcrumb label after fetching data.
csharp
// In a course details page model or controller action
private readonly IBreadcrumbsManager _breadcrumbsManager;
public CourseDetailsModel(IBreadcrumbsManager breadcrumbsManager, /* other services */)
{
_breadcrumbsManager = breadcrumbsManager;
}
public async Task<IActionResult> OnGetAsync(string slug)
{
var course = await _contentfulClient.GetEntryBySlug<Course>(slug);
if (course == null) return NotFound();
// The middleware created a breadcrumb with the label "a-course-slug".
// We replace it with the actual course title.
_breadcrumbsManager.ReplaceCrumbForSlug(slug, course.Title);
// ... rest of the action
return Page();
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
IVisitedLessonsManager / VisitedLessons
This service provides a simple, client-side mechanism for tracking which lessons and courses a user has visited. This state is persisted across requests using a browser cookie.
Implementation Details
- Cookie-Based Storage: The manager reads and writes a cookie named
ContentfulVisitedLessons. The cookie's value is a semicolon-delimited string of visited lesson/course IDs. - Persistence: The cookie is set to expire 7 days after the last visited lesson is added, providing short-to-medium-term persistence.
- Initialization: On instantiation, the manager reads the cookie from the current request and populates the
VisitedLessonslist. - State Modification: The
AddVisitedLessonmethod appends a new ID to the list and updates the cookie in the HTTP response.
API Reference
The IVisitedLessonsManager interface exposes the following members:
| Member | Type | Description |
|---|---|---|
VisitedLessons | List<string> | (Get-only) A list of unique IDs for all lessons and courses the user has visited. |
AddVisitedLesson(string lessonId) | void | Adds the specified lessonId to the list of visited items and updates the client-side cookie. |
Technical Considerations
- Cookie Size Limit: Browsers impose a size limit on cookies (typically ~4KB). If a user visits a very large number of lessons, this limit could be exceeded, leading to data loss.
- Client-Side State: Since the state is stored on the client, it can be cleared or manipulated by the user. This implementation is suitable for non-critical features like UI indicators but should not be used for business logic that requires authoritative state tracking.
ModulesResolver
The ModulesResolver is a specialized class that implements the IContentTypeResolver interface from the Contentful.NET SDK. Its role is crucial for handling polymorphic content, where a single field in Contentful (like a "modules" reference field) can contain links to entries of different content types (e.g., Hero Image, Copy Block, Highlighted Course).
Implementation Details
- Type Mapping: The resolver maintains a static
Dictionary<string, Type>that maps a Contentful Content Type ID (a string) to a specific C# model class (Type). - Deserialization Hook: During the JSON deserialization process, the Contentful SDK encounters an entry in a collection. It calls the
Resolve(contentTypeId)method with the entry's content type ID. - Type Resolution: The
ModulesResolverlooks up the ID in its dictionary and returns the corresponding C# type. The SDK then uses this type information to correctly deserialize the JSON object into the right C# class instance. If no type is found, it returnsnull, and the SDK may fall back to a default type or skip the item.
Configuration
The ModulesResolver is not typically injected or used directly in application logic. Instead, an instance is created and assigned to the ContentfulOptions.ContentTypeResolver property during the configuration of the ContentfulClient.
For detailed setup, refer to the service configuration documentation at /configuration/services.md.
Code Snippet: ModulesResolver Definition
csharp
// TheExampleApp/Configuration/ModulesResolver.cs
/// <summary>
/// Resolves a strong type from a content type id. Instructing the serialization engine how to deserialize items in a collection.
/// </summary>
public class ModulesResolver : IContentTypeResolver
{
private Dictionary<string, Type> _types = new Dictionary<string, Type>()
{
{ "layoutCopy", typeof(LayoutCopy) },
{ "layoutHeroImage", typeof(LayoutHeroImage) },
{ "layoutHighlightedCourse", typeof(LayoutHighlightedCourse) },
{ "lessonCodeSnippets", typeof(LessonCodeSnippets) },
{ "lessonCopy", typeof(LessonCopy) },
{ "lessonImage", typeof(LessonImage) },
};
/// <summary>
/// Method to get a type based on the specified content type id.
/// </summary>
public Type Resolve(string contentTypeId)
{
return _types.TryGetValue(contentTypeId, out var type) ? type : null;
}
}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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Note: Whenever a new polymorphic module type is created in Contentful and a corresponding C# model is added, the
ModulesResolverdictionary must be updated with the new mapping. See /api_reference/models.md for information on the model classes.
Localization and IViewLocalizer
The application is designed for internationalization (i18n) using a JSON-based localization provider. While the provider's source code is not shown here, its usage is evident in components like the Breadcrumbs middleware. The core of this system is the IViewLocalizer service provided by ASP.NET Core.
Implementation and Usage
- JSON Resource Files: The
tech_stackindicates the presence ofen-US.jsonandde-DE.jsonfiles. These files contain key-value pairs for localizable strings. IViewLocalizerService: This service is injected into components that require text localization. It abstracts away the process of loading and selecting the correct string based on the current request's culture.- Usage in
BreadcrumbsMiddleware: TheBreadcrumbsmiddleware injectsIViewLocalizerto translate static and dynamic path segments into user-friendly labels. It constructs a key (e.g.,coursesLabel) and requests the localized string from the service.
Localization Key Convention
The code follows a convention where a path segment is transformed into a camelCase string with a Label suffix to form the localization key.
- Path:
/courses-> Key:coursesLabel - Path:
/about-us-> Segment:about-us-> Normalized:about us-> Key:aboutUsLabel
Example JSON Resource (en-US.json)
Based on the usage in Breadcrumbs.cs, a resource file would look like this:
json
{
"homeLabel": "Home",
"coursesLabel": "Courses",
"settingsLabel": "Settings"
}1
2
3
4
5
2
3
4
5