GitHub - lstevens297/RazorRenderer: 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.

3 min read Original article ↗

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 IViewRenderer through dependency injection
  • Recursively discovers .cshtml files 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.sln

Quick 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.cshtml becomes Welcome
  • Pages/Emails/Receipt.cshtml becomes Receipt

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
  • @model for typed Model access in generated views
  • @using directives 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 @model is 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:

  • RazorCompilationException
  • ViewNotFoundException
  • RazorRuntimeException

Solution Layout

  • RazorRenderer.Core/ contains the library and public API
  • RazorRenderer.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.