RazorRenderer is a small .NET 9 library for compiling and rendering .cshtml templates without ASP.NET MVC. It focuses on a minimal runtime pipeline: discover views under the application content root, compile them on demand, cache the generated types, and render by logical view name.
What It Does
- Registers a singleton
IViewRendererthrough dependency injection - Recursively discovers
.cshtmlfiles from the host content root - Resolves views by file name
- Compiles templates into in-memory assemblies on first render
- Reuses compiled view delegates on later renders
Requirements
- .NET SDK 9.0 or later
Installation
NuGet
dotnet add package RazorRenderer
From source
git clone https://github.com/lstevens297/RazorRenderer.git
cd RazorRenderer
dotnet build RazorRenderer.slnQuick Start
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RazorRenderer.Core; var builder = Host.CreateApplicationBuilder(args); builder.Services.AddRazorRenderer(); using var app = builder.Build(); var renderer = app.Services.GetRequiredService<IViewRenderer>(); var html = renderer.Render("Welcome", new { FirstName = "Ada", LastName = "Lovelace" });
Example template:
<!DOCTYPE html> <html> <head> <title>Welcome</title> </head> <body> <h1>Hello, @(Model?.FirstName ?? "Friend")!</h1> </body> </html>
Public API
public interface IViewRenderer { string Render(string viewName, object? model = null); }
Service registration:
builder.Services.AddRazorRenderer();
View Discovery
AddRazorRenderer() resolves IHostEnvironment, scans the content root recursively for .cshtml files, and registers them into the renderer.
View names are currently derived from the file name only:
Views/Welcome.cshtmlbecomesWelcomePages/Emails/Receipt.cshtmlbecomesReceipt
If two files share the same name in different folders, the later registration wins.
Supported Template Features
The current compiler supports a limited subset of Razor-style templates:
- Literal HTML and text
@modelfor typedModelaccess in generated views@usingdirectives copied into generated code- Inline expressions such as
@Model.Name - Parenthesized expressions such as
@(Model?.FirstName ?? "Friend") - Simple
@{ ... }code blocks - Basic block control flow such as
@foreach,@if,@else,@for, and@while - Optional models passed in as
object?, with typed access when@modelis specified and dynamic access otherwise
| Feature | RazorRenderer | Full Razor |
|---|---|---|
| Literal HTML and text | Supported | Supported |
Inline expressions like @Model.Name |
Supported | Supported |
Parenthesized expressions like @( ... ) |
Supported | Supported |
@model directive |
Supported for typed generated Model |
Supported |
@using directive |
Supported | Supported |
@{ ... } code blocks |
Supported | Supported |
Basic control flow like @if, @else, @for, @foreach, @while |
Supported | Supported |
@layout |
Ignored | Supported |
@inject |
Ignored | Supported |
| Partials and HTML helpers | Not supported | Supported |
| Sections and view start files | Not supported | Supported |
| Tag Helpers | Not supported | Supported |
| Compile-time model validation and MVC integration | Not supported | Supported |
| Source mapping and Razor diagnostics parity | Not supported | Supported |
These directives are still ignored by the current implementation if they appear at the start of a line:
@layout@inject
Limitations
The current implementation is intentionally narrow and does not yet provide full Razor semantics.
- No layout support
- No partial rendering helper API
- No HTML helper layer
- No compile-time model validation
- No source mapping back to
.cshtml
Exceptions
The core project exposes these runtime exception types:
RazorCompilationExceptionViewNotFoundExceptionRazorRuntimeException
Solution Layout
RazorRenderer.Core/contains the library and public APIRazorRenderer.Examples/contains a sample web application and example views
Build And Pack
Build the solution:
dotnet build RazorRenderer.sln
Pack the core library:
dotnet pack RazorRenderer.Core/RazorRenderer.Core.csproj -c Release
Example App
The sample app in RazorRenderer.Examples/ shows how to inject IViewRenderer into endpoints and render views at runtime.
Run it with:
dotnet run --project RazorRenderer.Examples
License
MIT. See LICENSE.