Appearance
Are you an LLM? You can read better optimized documentation at /api_reference/view_components.md for this page in Markdown format
View Components
This document provides a detailed technical reference for the View Components used in TheExampleApp. View Components are self-contained, reusable rendering units in ASP.NET Core, similar to partial views but more powerful. They are used throughout the application to encapsulate complex UI logic, interact with external services like Contentful, and manage application state.
Each section below details the public API, implementation logic, and usage patterns for a specific View Component.
LocalesViewComponent
This component is responsible for rendering the language/locale selection dropdown. It fetches available locales from the Contentful space and manages the currently selected locale via the user's session.
Implementation Details
The component's primary task is to provide a list of all configured locales within the Contentful space.
- Data Fetching: It uses an injected
IContentfulClientto call_client.GetSpace(), which returns aSpaceobject containing a list ofLocaleobjects. - Error Handling: A critical feature is its resilience to API failures. If the call to
_client.GetSpace()fails (e.g., due to invalid credentials during initial setup), it catches the exception and provides a defaultLocalelist containing only "en-US". This prevents the entire application from crashing if the Contentful configuration is incorrect. - State Management: The currently selected locale is persisted in the user's session using the key defined in
Startup.LOCALE_KEY. On invocation, it reads this value. If no value is found in the session, it defaults to the server's current culture (CultureInfo.CurrentCulture). It then ensures the resolved locale is set back into the session for subsequent requests.
For more information on how localization is handled application-wide, see the Internationalization documentation.
API Signature
The component is invoked asynchronously and does not require any parameters.
csharp
// TheExampleApp/ViewComponents/LocalesViewComponent.cs
public class LocalesViewComponent : ViewComponent
{
private readonly IContentfulClient _client;
public LocalesViewComponent(IContentfulClient client)
{
_client = client;
}
public async Task<IViewComponentResult> InvokeAsync()
{
// ... implementation ...
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
View Model: LocalesInfo
The component passes a LocalesInfo object to its view.
| Property | Type | Description |
|---|---|---|
Locales | List<Locale> | The list of all available locales fetched from the Contentful space. |
SelectedLocale | Locale | The currently active locale for the user. |
UsePreviewApi | bool | A flag indicating if the application is currently using the Preview API. |
Invocation Example
To render the locale selector in a Razor view (e.g., _Layout.cshtml), use the following tag helper or method call:
csharp
// Using the Tag Helper
<vc:locales></vc:locales>
// Or using the InvokeAsync method
@await Component.InvokeAsync("Locales")1
2
3
4
5
2
3
4
5
EntryStateViewComponent
This component displays the publication status of one or more Contentful entries, indicating whether they are drafts, published, or have pending changes. This is a key part of the editorial experience.
Implementation Details
The logic for determining an entry's state is non-trivial and involves comparing data from both the Delivery and Preview APIs.
- Forced Delivery API Call: Regardless of the application's current API mode, this component always queries the Delivery API to get the public, published state of entries. It achieves this by instantiating a new, temporary
ContentfulClientwith theusePreviewApiflag explicitly set tofalse. - Bulk Entry Checking: The component accepts multiple entry system properties and queries all of them in a single API call using the
sys.id[in]=filter syntax (e.g.,sys.id[in]=id1,id2,id3). - Draft Detection: The entries are considered to have a draft if the forced call to the Delivery API either throws an exception, returns no results, or returns fewer entries than requested. This means at least one entry exists in the Preview API but not the Delivery API.
- Pending Changes Detection: The entries have pending changes if they exist in both the Delivery and Preview APIs, but any of their
sys.updatedAttimestamps do not match.- Timestamp Precision: The component includes a private helper method,
TrimMilliseconds, to compareDateTimeobjects. This is a crucial gotcha, as the precision of timestamps returned by the Contentful APIs can vary slightly, leading to false positives for pending changes if not handled correctly.
- Timestamp Precision: The component includes a private helper method,
csharp
// TheExampleApp/ViewComponents/EntryStateViewComponent.cs
// The component creates a new client to specifically target the Delivery API.
var client = new ContentfulClient(_httpClient, _options.DeliveryApiKey, _options.PreviewApiKey, _options.SpaceId, false);
// ...
// Logic to compare timestamps after trimming milliseconds.
DateTime? TrimMilliseconds(DateTime? dateTime)
{
if (!dateTime.HasValue) { return dateTime; }
return new DateTime(dateTime.Value.Year, dateTime.Value.Month, dateTime.Value.Day,
dateTime.Value.Hour, dateTime.Value.Minute, dateTime.Value.Second, 0);
}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
API Signature
The component requires the system properties of the entry (or entries) to be checked. These properties should come from the version of the entry fetched via the Preview API.
csharp
// TheExampleApp/ViewComponents/EntryStateViewComponent.cs
public class EntryStateViewComponent : ViewComponent
{
// ... constructor ...
public async Task<IViewComponentResult> InvokeAsync(IEnumerable<SystemProperties> sys)
{
// ... implementation ...
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
View Model: EntryStateModel
| Property | Type | Description |
|---|---|---|
Sys | SystemProperties | The system properties of the entry being checked. |
Draft | bool | true if the entry is not published. |
PendingChanges | bool | true if the entry is published but has unpublished changes. |
Invocation Example
This component is typically invoked on a page that displays content from one or more Contentful entries.
csharp
// Pass the SystemProperties of a single entry to the component.
@await Component.InvokeAsync("EntryState", new { sys = new List<SystemProperties> { Model.Sys } })
// Or check multiple entries at once (e.g., when displaying a collection).
@await Component.InvokeAsync("EntryState", new { sys = Model.Items.Select(item => item.Sys) })1
2
3
4
5
2
3
4
5
MetaTagsViewComponent
This component is responsible for generating the HTML <title> tag for each page, ensuring a consistent title format across the application.
Implementation Details
The component uses the IViewLocalizer service to construct a localized page title.
- Default Title: If no specific title is provided to the component, it uses a default title retrieved from the localization resources (e.g.,
en-US.json) with the key"defaultTitle". - Formatted Title: If a
titleparameter is passed, it prepends this to the default title, creating a format likePage Specific Title — Site Default Title.
This simple but centralized approach ensures all pages share a consistent and localizable title structure. For more details on localization, see the Internationalization documentation.
API Signature
The component accepts an optional title string.
csharp
// TheExampleApp/ViewComponents/MetaTagsViewComponent.cs
public class MetaTagsViewComponent : ViewComponent
{
// ... constructor ...
public IViewComponentResult Invoke(string title)
{
// ... implementation ...
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
View Model
This component does not use a complex model. It passes the final, formatted string directly to its view (Default.cshtml), which then renders the <title> tag.
Invocation Example
This component should be called from the main layout file (/views/layout.md) within the <head> section.
csharp
// In _Layout.cshtml, using a title from the current page's model
@await Component.InvokeAsync("MetaTags", new { title = Model?.Title })
// If no title is passed, it will use the default.
@await Component.InvokeAsync("MetaTags")1
2
3
4
5
2
3
4
5
SelectedApiViewComponent
This component renders the UI for switching between the Contentful Delivery and Preview APIs. This is a development and editorial tool.
Implementation Details
The component's main responsibility is to determine the current API mode and provide the necessary information to its view to render a switcher.
- API Mode Detection: It inspects the injected
IContentfulClient'sIsPreviewClientproperty to determine if the application is currently in preview mode. - Redirect Path: It accepts a
currentPathparameter, which is crucial for redirecting the user back to the correct page after the API mode is changed. The view will use this path to construct the correct links for the switcher.
For details on how the API mode is configured and managed, refer to the Configuration documentation.
API Signature
The component requires the path of the current request.
csharp
// TheExampleApp/ViewComponents/SelectedApiViewComponent.cs
public class SelectedApiViewComponent : ViewComponent
{
// ... constructor ...
public IViewComponentResult Invoke(string currentPath)
{
// ... implementation ...
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
View Model
The component passes a Tuple<bool, string> to its view.
Item1(bool):trueif the Preview API is active,falseotherwise.Item2(string): The current request path, to be used for redirection.
Invocation Example
This component is typically rendered in a shared layout file, such as the header or footer.
csharp
// In _Layout.cshtml, pass the current request path.
@await Component.InvokeAsync("SelectedApi", new { currentPath = Context.Request.Path })1
2
2
EditorialFeaturesViewComponent
This component renders contextual UI elements for content editors, such as "Open in Contentful" links that navigate directly to the entry editing interface in the Contentful web app.
Implementation Details
The visibility of these features is controlled by a session flag.
- Feature Flag: The component checks
HttpContext.Session.GetString("EditorialFeatures") == "Enabled"to determine if the UI should be rendered. This allows the features to be toggled on or off for a user's session. - Link Generation: To build the direct link to the Contentful web app, the component requires the
SpaceId(fromContentfulOptions) and theSysproperties of the entry (or entries) being displayed. - API Context: It also checks the
UsePreviewApioption to provide context to the view, as editorial features are typically only relevant when using the Preview API.
API Signature
The component requires the system properties of the content being displayed.
csharp
// TheExampleApp/ViewComponents/EditorialFeaturesViewComponent.cs
public class EditorialFeaturesViewComponent : ViewComponent
{
// ... constructor ...
public IViewComponentResult Invoke(IEnumerable<SystemProperties> sys)
{
// ... implementation ...
}
}1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
View Model: EditorialFeaturesModel
| Property | Type | Description |
|---|---|---|
Sys | IEnumerable<SystemProperties> | The system properties of the entry, used to build the direct edit link. |
FeaturesEnabled | bool | true if the editorial features are enabled in the current session. |
UsePreviewApi | bool | true if the application is configured to use the Preview API. |
SpaceId | string | The ID of the current Contentful space. |
Invocation Example
This component should be invoked near the content it relates to, allowing an editor to easily access the source entry.
csharp
// Pass the SystemProperties of the current model to the component.
@await Component.InvokeAsync("EditorialFeatures", new { sys = new List<SystemProperties> { Model.Sys } })1
2
2