| name | orchardcore-razor |
| description | Skill for building Razor views in Orchard Core themes and modules. Covers tag helpers, shape rendering, resource management, IOrchardHelper extensions, layout patterns, and _ViewImports.cshtml setup. Use this skill when requests mention Orchard Core Razor Views, _ViewImports.cshtml Setup, Minimum Required Directives, _ViewStart.cshtml Conventions, Layout Rendering Patterns, Minimal Layout Template, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with OrchardCore.DisplayManagement, OrchardCore.ResourceManagement, OrchardCore.Menu, OrchardCore.Contents, OrchardCore.Media, OrchardCore.DisplayManagement.Shapes, OrchardCore.ContentManagement, OrchardCore.DisplayManagement.Razor, IOrchardHelper. It also helps with razor examples, Layout Rendering Patterns, Minimal Layout Template, Shape Tag Helpers, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill. |
| license | Apache-2.0 |
| metadata | {"author":"CrestApps Team","version":"1.0"} |
Orchard Core Razor Views - Prompt Templates
_ViewImports.cshtml Setup
Every Orchard Core theme or module should include a _ViewImports.cshtml file at the root of its Views folder.
Minimum Required Directives
@inherits OrchardCore.DisplayManagement.Razor.RazorPage<TModel>
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, OrchardCore.DisplayManagement
@addTagHelper *, OrchardCore.ResourceManagement
@addTagHelper *, OrchardCore.Menu
@addTagHelper *, OrchardCore.Contents
@addTagHelper *, OrchardCore.Media
@using OrchardCore.DisplayManagement
@using OrchardCore.DisplayManagement.Shapes
@using OrchardCore.ContentManagement
@using Microsoft.AspNetCore.Html
Guidelines
@inherits OrchardCore.DisplayManagement.Razor.RazorPage<TModel> gives access to IOrchardHelper via Orchard and shape display helpers.
- Add only the
@addTagHelper lines for assemblies your theme or module actually uses.
@using OrchardCore.DisplayManagement.Razor is not needed when @inherits already references that namespace.
- For themes, add
@using OrchardCore to access general extension methods.
_ViewStart.cshtml Conventions
@{
Layout = "Layout";
}
- Place
_ViewStart.cshtml in the Views folder to set the default layout.
"Layout" references the shape named Layout which resolves to Layout.cshtml.
- Modules typically do not set a layout in
_ViewStart.cshtml because their views render inside the theme's layout automatically.
- Override per-view by setting
Layout = null; for partial or layoutless pages.
Layout Rendering Patterns
A theme's Layout.cshtml renders zones that contain shapes placed by modules and the admin UI.
Minimal Layout Template
@{
var body = await RenderBodyAsync();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@RenderTitleSegments(Site.SiteName)</title>
<resources type="Meta" />
<style asp-name="{{ThemeStyleName}}"></style>
<resources type="HeadLink" />
<resources type="HeadScript" />
<resources type="StyleSheet" />
</head>
<body>
<zone name="Header" />
<zone name="Content">
@body
</zone>
<zone name="Footer" />
<resources type="FooterScript" />
</body>
</html>
Guidelines
- Always call
await RenderBodyAsync() before rendering any zone that wraps it, so the body content registers its resources first.
- Use
@RenderTitleSegments(Site.SiteName) to render page title segments separated by the site name.
- Render resource tags in the correct location:
Meta, HeadLink, HeadScript, StyleSheet in <head>, and FooterScript before </body>.
Shape Tag Helpers
Shapes are the fundamental rendering unit in Orchard Core. Use tag helpers to display and compose shapes.
Display a Shape
<shape type="{{ShapeType}}" />
Display a Shape with Properties
<shape type="{{ShapeType}}" prop-title="@item.Title" prop-content="@item.Content" />
- Prefix shape properties with
prop- to pass data into the shape template.
Display a Dynamic Shape Object
When you have a shape object (e.g., from a zone or shape table), render it with display:
@await DisplayAsync(Model)
@await DisplayAsync(Model.Content)
Named Shapes with Cache
<shape type="{{ShapeType}}" cache-id="{{unique-id}}" cache-expires-after="@TimeSpan.FromMinutes(5)" />
Zone Tag Helper
Zones are named buckets in the layout that collect shapes for rendering.
Render a Zone
<zone name="{{ZoneName}}" />
Render a Zone with Wrapper Content
<zone name="{{ZoneName}}">
<div class="container">
@RenderBody()
</div>
</zone>
Conditional Zone Rendering
Check if a zone has content before rendering its wrapper:
@if (Model.{{ZoneName}} != null)
{
<aside>
<zone name="{{ZoneName}}" />
</aside>
}
Common zone names: Header, Navigation, Content, Sidebar, Footer, AfterContent, BeforeContent.
Link Generation
In Orchard Core views, prefer MVC tag helpers so link generation stays in the Razor template and remains route-aware.
Preferred View Pattern
<a asp-action="Edit" asp-controller="Admin" asp-area="MyModule" asp-route-id="@Model.ContentItemId">
@T["Edit"]
</a>
Guidelines
- Prefer
asp-action, asp-controller, and when needed asp-area instead of hard-coded application URLs.
- Do not use
@Url.Content("~/...") to generate application links in Orchard Core views.
- Keep link generation in the view when possible so routes stay explicit and easy to override.
- Continue using normal tag helpers for forms and buttons, such as
<form asp-action="Update" method="post">.
URL Generation in Code
If a URL must be generated outside the view, inject LinkGenerator and pass the current HttpContext so Orchard Core generates the correct route-aware URL.
using Microsoft.AspNetCore.Routing;
public sealed class AdminLinkService
{
private readonly LinkGenerator _linkGenerator;
public AdminLinkService(LinkGenerator linkGenerator)
{
_linkGenerator = linkGenerator;
}
public string? GetEditUrl(HttpContext httpContext, string contentItemId)
{
return _linkGenerator.GetPathByAction(
httpContext,
action: "Edit",
controller: "Admin",
values: new
{
area = "MyModule",
id = contentItemId,
});
}
}
Resource Tag Helpers
Register a Stylesheet
<style asp-name="{{ResourceName}}"></style>
Register a Stylesheet with a CDN Fallback
<style asp-name="{{ResourceName}}" version="{{Version}}" cdn-url="{{CdnUrl}}"></style>
Register a Script at the Foot of the Page
<script asp-name="{{ResourceName}}" at="Foot"></script>
Register a Script at the Head
<script asp-name="{{ResourceName}}" at="Head"></script>
Register an Inline Script
<script at="Foot">
document.addEventListener('DOMContentLoaded', function () {
console.log('Page loaded');
});
</script>
Script Dependencies
<script asp-name="{{ResourceName}}" depends-on="jQuery" at="Foot"></script>
Render All Registered Resources
Place these in the layout to output all resources registered by shapes and modules:
<resources type="Meta" />
<resources type="HeadLink" />
<resources type="HeadScript" />
<resources type="StyleSheet" />
<resources type="FooterScript" />
Resource Positions
| Position | Description |
|---|
Head | Rendered in <head> via <resources type="HeadScript" /> |
Foot | Rendered before </body> via <resources type="FooterScript" /> |
Media Tag Helper
Render an Image from the Media Library
<img asp-src="@Model.ContentItem.Content.{{PartName}}.{{FieldName}}.Paths[0]" />
Resize an Image
<img asp-src="@imagePath" asp-resize-width="300" />
Resize with Width and Height
<img asp-src="@imagePath" asp-resize-width="800" asp-resize-height="600" />
Resize Modes
<img asp-src="@imagePath" asp-resize-width="400" asp-resize-height="400" asp-resize-mode="Crop" />
| Mode | Description |
|---|
Pad | Resize and pad to fit the target dimensions |
BoxPad | Pad the image to fit within the bounding box |
Crop | Resize and crop to fill the target dimensions |
Min | Resize to the minimum of the target dimensions |
Max | Resize to the maximum of the target dimensions |
Stretch | Stretch the image to fill the target dimensions |
Content Tag Helpers
Render a Content Item
<contentitem alias="alias:{{alias}}" display-type="Summary" />
Render a Content Item by Content Item ID
<contentitem content-item-id="@Model.ContentItem.ContentItemId" display-type="Detail" />
Common Display Types
| Display Type | Description |
|---|
Detail | Full detail view |
Summary | Abbreviated summary view |
SummaryAdmin | Admin-specific summary |
Menu Tag Helper
Render a Named Menu
<menu alias="alias:main-menu" />
- The
alias attribute specifies the alias of the menu content item.
- The menu renders using the menu shape templates, which can be overridden in your theme.
Caching Tag Helper
Cache a Section of Markup
<cache expires-after="@TimeSpan.FromMinutes(10)">
<p>This content is cached for 10 minutes.</p>
</cache>
Cache with a Vary-By Key
<cache expires-after="@TimeSpan.FromMinutes(5)" vary-by="@Context.Request.Path">
@await DisplayAsync(Model.Content)
</cache>
Cache Attributes
| Attribute | Description |
|---|
expires-after | TimeSpan after which the cache entry expires |
expires-on | Absolute DateTimeOffset for expiration |
expires-sliding | Sliding TimeSpan expiration window |
vary-by | Key to vary the cached output (e.g., per path or query) |
vary-by-user | When true, caches separately per authenticated user |
Date-Time and Time-Zone Tag Helpers
Render a UTC Date in the Site's Time Zone
<date-time utc="@Model.ContentItem.CreatedUtc" />
Render a Date with a Custom Format
<date-time utc="@Model.ContentItem.PublishedUtc" format="MMMM dd, yyyy" />
Render the Current Time Zone Name
<time-zone />
IOrchardHelper Extensions
Access IOrchardHelper via the Orchard property in Razor views that inherit from OrchardCore.DisplayManagement.Razor.RazorPage<TModel>.
Get a Content Item by ID
@{
var item = await Orchard.GetContentItemByIdAsync("{{contentItemId}}");
}
Get a Content Item by Version ID
@{
var item = await Orchard.GetContentItemByVersionIdAsync("{{contentItemVersionId}}");
}
Query Content Items
@{
var items = await Orchard.QueryContentItemsAsync(query =>
query.Where(index => index.ContentType == "BlogPost" && index.Published));
}
Get Content Items by Content Type
@{
var items = await Orchard.GetRecentContentItemsByContentTypeAsync("BlogPost", 10);
}
Get a Content Item by Alias
@{
var item = await Orchard.GetContentItemByHandleAsync("alias:{{alias}}");
}
Get Site Settings Value
@{
var siteName = Orchard.ConsoleLog(Site.SiteName);
}
Access global site settings via Site:
<p>@Site.SiteName</p>
<p>@Site.BaseUrl</p>
Liquid-to-HTML Rendering
@{
var html = await Orchard.LiquidToHtmlAsync("{{ 'now' | date: '%B %d, %Y' }}");
}
Content Item Display
@{
var shape = await Orchard.DisplayContentItemAsync(contentItem, "Summary");
}
@await DisplayAsync(shape)
Defining a Resource Manifest
Register stylesheets and scripts so they can be referenced by name in Razor views.
Resource Manifest Class
public sealed class ResourceManifest : IResourceManifestProvider
{
public void BuildManifests(IResourceManifestBuilder builder)
{
var manifest = builder.Add();
manifest.DefineStyle("{{ThemeStyleName}}")
.SetUrl("~/{{ModuleOrThemeId}}/css/site.min.css", "~/{{ModuleOrThemeId}}/css/site.css");
manifest.DefineScript("{{ThemeScriptName}}")
.SetUrl("~/{{ModuleOrThemeId}}/js/site.min.js", "~/{{ModuleOrThemeId}}/js/site.js")
.SetPosition("Foot");
}
}
Guidelines
- The first
SetUrl parameter is the minified version; the second is the debug version.
- Use
SetPosition("Foot") for scripts that should render before </body>.
- Use
SetDependencies("jQuery") to declare script dependencies.
- Register the manifest class in
Startup.cs:
public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddResourceManifest<ResourceManifest>();
}
}
Recipe Step for Themes
Set the Active Theme via Recipe
{
"steps": [
{
"name": "Themes",
"Site": "{{ThemeId}}",
"Admin": "TheAdmin"
}
]
}