Appearance
Are you an LLM? You can read better optimized documentation at /getting_started/introduction.md for this page in Markdown format
Introduction
Note: This repository is no longer officially maintained as of January 2023. Feel free to use it, fork it, and patch it for your own needs.
This document provides a detailed technical introduction to TheExampleApp. It is intended for developers who will be maintaining, extending, and troubleshooting the application. It covers the application's purpose, key architectural features, technology stack, and prerequisites for development.
What is TheExampleApp?
TheExampleApp is a reference web application built with ASP.NET Core 2.1. Its primary purpose is to serve as a comprehensive, real-world example of how to build a .NET application integrated with Contentful as a headless Content Management System (CMS).
As described in the project's app.json, it is "a reference for building your own applications using Contentful." It functions as a learning tool and a best-practice guide, demonstrating key concepts such as:
- Consuming content from the Contentful Delivery and Preview APIs.
- Structuring content models within Contentful for a course-based application.
- Implementing features like internationalization and dynamic routing based on CMS data.
- Decoupling the presentation layer (the .NET app) from the content layer (Contentful).
For a high-level architectural diagram and component breakdown, please see the Architecture Overview.
Key Features
The application implements several key features that showcase a robust integration with a headless CMS.
Contentful Integration
The core of the application is its integration with Contentful. It uses the contentful.aspnetcore SDK to fetch and display content. A notable customization in Startup.cs is the registration of a transient IContentfulClient, which enhances the default behavior.
csharp
// From: TheExampleApp/Startup.cs
// This customization allows for in-memory updates of Contentful options and
// adds a custom application identifier to API requests for tracking purposes.
services.AddTransient<IContentfulClient, ContentfulClient>((ip) => {
var client = ip.GetService<HttpClient>();
var options = ip.GetService<IContentfulOptionsManager>().Options;
var contentfulClient = new ContentfulClient(client,
options);
var version = typeof(Startup).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
.InformationalVersion;
contentfulClient.Application = $"app the-example-app.csharp/{version}; {contentfulClient.Application}";
return contentfulClient;
});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
The application also supports a staging environment via a custom HttpClientHandler, which can redirect API requests to a different host. This is useful for previewing content changes from a non-production Contentful environment.
csharp
// From: TheExampleApp/Startup.cs
// This handler intercepts outgoing HTTP requests and rewrites the URI
// to point to a staging host if one is configured.
public class StagingMessageHandler : HttpClientHandler
{
public string StagingHost { get; set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var regex = new Regex("contentful");
var req = regex.Replace(request.RequestUri.ToString(), StagingHost, 1);
request.RequestUri = new Uri(req);
return await base.SendAsync(request, cancellationToken);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Course and Lesson Management
The application's domain is centered around managing educational courses and lessons. It uses ASP.NET Core's Razor Pages with custom routing conventions defined in Startup.cs to create user-friendly and SEO-friendly URLs.
csharp
// From: TheExampleApp/Startup.cs
// These conventions map dynamic URL segments to specific Razor Pages,
// allowing for routes like /Courses/hello-contentful/lessons/what-is-contentful
services.AddMvc().AddRazorPagesOptions(
options => {
options.Conventions.AddPageRoute("/Courses", "Courses/Categories/{category?}");
options.Conventions.AddPageRoute("/Courses/Index", "Courses/{slug}/lessons");
options.Conventions.AddPageRoute("/Courses/Lessons", "Courses/{slug}/lessons/{lessonSlug}");
});1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Advanced Internationalization (i18n)
The application has a sophisticated internationalization strategy that combines static resource files with dynamic locale information from Contentful.
- Supported Locales: The application explicitly supports
en-USandde-DE, with translations stored as embedded JSON resources (en-US.json,de-DE.json). - Locale Detection: A
CustomRequestCultureProviderinStartup.csdefines the locale resolution logic:- A
localequery string parameter (e.g.,?locale=de-DE) has the highest priority. - The application validates the requested locale against the list of available locales in the Contentful space.
- If the application does not have static translations for a valid Contentful locale, it traverses the fallback chain defined in Contentful (e.g.,
de-AT->de-DE) until it finds a locale supported by the application. - The resolved locale is stored in the user's session to persist across requests.
- A
Markdown Rendering
Content fields within Contentful are expected to be authored in Markdown. The application uses the Markdig library (Markdig, Version=0.15.4) to parse this Markdown and render it as HTML within the Razor views. This allows content editors to use rich text formatting without writing HTML.
Technology Overview
The application is built on the .NET Core 2.1 platform, leveraging a specific set of libraries and frameworks to achieve its functionality. For a more detailed breakdown of the components, refer to the Architecture Overview.
| Technology | Version | Description |
|---|---|---|
| .NET Core | 2.1 | The underlying runtime and framework. |
| ASP.NET Core | 2.1.5 | The web framework metapackage (Microsoft.AspNetCore.All). |
| Razor Pages | 2.1.2 | The server-side UI framework. |
| Contentful SDK | 3.3.6 | Client library for the Contentful headless CMS. |
| Markdig | 0.15.4 | A high-performance Markdown processor for .NET. |
| xUnit | 2.3.1 | The test execution framework for the unit test suite. |
| Moq | 4.7.145 | The mocking framework used for isolating dependencies in tests. |
The frontend is primarily server-rendered using Razor. While a bower.json file exists, it contains no dependencies, indicating a deliberate choice to minimize client-side JavaScript and rely on server-generated HTML.
Prerequisites
To effectively work on this project, developers should possess the following knowledge and have the specified tools installed.
Technical Knowledge
- C# and .NET Core: Strong proficiency is required.
- ASP.NET Core: Solid understanding of middleware, dependency injection, configuration, and Razor Pages.
- Headless CMS Concepts: Familiarity with the principles of separating content management from presentation.
- Unit Testing: Experience with xUnit and mocking using frameworks like Moq.
Required Tools
- .NET Core SDK 2.1 or a compatible version.
- Git for source control.
- An IDE such as Visual Studio, JetBrains Rider, or Visual Studio Code.
- A Contentful account. While the app can run in a read-only mode against a demo space, read/write access to your own space is required for development and testing content changes.
- Contentful CLI: Recommended for creating and seeding a new Contentful space with the required content model.
For detailed setup instructions, please follow the Installation Guide.
Who Should Use This Documentation?
This documentation is for the technical development team responsible for the application. This includes:
- Backend and Full-Stack Developers who are maintaining or extending the application's features.
- New Team Members who need to onboard and understand the codebase and architecture.
- DevOps Engineers responsible for the application's build and deployment pipeline.
After reading this introduction, a good next step is to follow the Quick Start Guide to get a local instance of the application up and running.