Aeroverra.RazorToString 1.0.1

dotnet add package Aeroverra.RazorToString --version 1.0.1
                    
NuGet\Install-Package Aeroverra.RazorToString -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Aeroverra.RazorToString" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Aeroverra.RazorToString" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Aeroverra.RazorToString" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Aeroverra.RazorToString --version 1.0.1
                    
#r "nuget: Aeroverra.RazorToString, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Aeroverra.RazorToString@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Aeroverra.RazorToString&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Aeroverra.RazorToString&version=1.0.1
                    
Install as a Cake Tool

AeroRazorToString

Build NuGet Downloads

Render Razor views to HTML strings from anywhere. No web host required.

Purpose

Razor is the best templating engine .NET has, and ASP.NET Core will only run it for you inside a web request. The moment you want an HTML string instead of a response body, from a worker service sending an email, a console tool generating a report, a queue consumer building a PDF, you are on your own.

The pieces to do it by hand are all public, which is why every codebase ends up with the same copy of the same fifteen year old sample: fake an HttpContext, fake an ActionContext, point a StringWriter at the view engine. That sample stops working the moment there is no web host, because MVC quietly assumes one: no IWebHostEnvironment, no diagnostic listener, no object pool provider, and no application parts to harvest compilation references from. What you get instead is a namespace 'Hosting' does not exist error from a Razor compiler with nothing to compile against.

This package is that problem solved once, tested against a worker service, a web app, and a bare ServiceCollection.

  • One line of registration, one method to call, works the same in every host
  • Layouts, partials, _ViewStart, _ViewImports, tag helpers, and ViewData all behave normally
  • @inject resolves against a fresh DI scope per render, so a scoped DbContext in a view is a scoped DbContext and not a process lifetime singleton shared across concurrent renders
  • Views are read from the output folder, and the package's build targets put them there for you
  • Views can also come from any other folder, from a file provider with no disk behind it, or from a Razor class library where they are already compiled
  • A view that will not compile, or a view name that matches nothing, says so in a way you can act on

Install

dotnet add package Aeroverra.RazorToString

Requires .NET 10. Your .cshtml files are copied next to the built app automatically; no csproj changes needed.

Use it

Register once, in any host:

builder.Services.AddRazorToString();

Inject IRazorToStringRenderer anywhere and render:

public class OrderCompleteEmailBuilder(IRazorToStringRenderer razor)
{
    public async Task<string> BuildAsync(Order order)
    {
        return await razor.RenderAsync("/Emails/OrderComplete.cshtml", new OrderCompleteModel
        {
            CustomerName = order.CustomerName,
            SerialCodes = order.SerialCodes
        });
    }
}

That is the whole API in a worker service, a console app, an Azure Function, or a web app. The view is an ordinary .cshtml file with an ordinary @model directive.

What it does for you

AddRazorToString() looks at the service collection and decides what is missing:

In a web app In a worker service, console app, or bare container
Uses the host's IWebHostEnvironment, application parts, and compilation references Registers a stand in IWebHostEnvironment rooted at the output folder
Adds the output folder as an extra view location, so views shipped inside a class library resolve Registers the DiagnosticListener and ObjectPoolProvider MVC assumes a web host provided
Leaves the app's own content root at higher priority, so its views stay editable at run time Hands the runtime compiler a reference set built from the loaded assemblies, the output folder, and the shared frameworks

Either way you get the same singleton renderer, safe to call concurrently.

Views that are not on disk

Runtime compilation is the default because it lets a template be edited without a rebuild. It is not the only source:

builder.Services.AddRazorToString(options =>
{
    options.AdditionalViewRoots.Add("/etc/myapp/templates");        // an operator editable folder
    options.FileProviders.Add(new ManifestEmbeddedFileProvider(assembly));
    options.ApplicationParts.Add(typeof(EmailTemplates).Assembly);  // compiled into a Razor class library
});

Set options.UseRuntimeCompilation = false to render only views compiled into application parts, which trades editability for never shipping a .cshtml file.

Documentation

Full documentation, including host modes, how view names resolve, every option, precompiled views, and the gotchas worth knowing about, lives in the wiki.

License

MIT. See LICENSE.md.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 110 8/17/2026