Regira.Web
6.6.0
dotnet add package Regira.Web --version 6.6.0
NuGet\Install-Package Regira.Web -Version 6.6.0
<PackageReference Include="Regira.Web" Version="6.6.0" />
<PackageVersion Include="Regira.Web" Version="6.6.0" />
<PackageReference Include="Regira.Web" />
paket add Regira.Web --version 6.6.0
#r "nuget: Regira.Web, 6.6.0"
#:package Regira.Web@6.6.0
#addin nuget:?package=Regira.Web&version=6.6.0
#tool nuget:?package=Regira.Web&version=6.6.0
Regira Web
Regira Web provides Razor-based HTML template rendering plus common web utilities, middleware, and Swagger configuration.
Projects
| Project | Package | Purpose |
|---|---|---|
Common.Web |
Regira.Web |
Core web utilities, middleware, exception handling |
Web.Analytics |
Regira.Web.Analytics |
Abstract visitor analytics — pluggable capture, enrichment, and storage hooks |
Web.Analytics.GeoIP2 |
Regira.Web.Analytics.GeoIP2 |
Country/city enrichment from a local MaxMind GeoIP2/GeoLite2 database |
Web.HTML.RazorComponents |
Regira.Web.HTML.RazorComponents |
Razor components (.razor) compiled with the app, rendered via ASP.NET Core's HtmlRenderer |
Web.HTML.RazorEngineCore |
Regira.Web.HTML.RazorEngineCore |
Razor templates via RazorEngineCore |
Web.HTML.RazorLight |
Regira.Web.HTML.RazorLight |
Razor templates via RazorLight |
Web.Swagger |
Regira.Web.Swagger |
Swagger/OpenAPI JWT & API Key support |
Host configuration (WebHostOptions), background task queues and the Windows Service installer live in Regira.System.Hosting — see System.
Installation
<PackageReference Include="Regira.Web" Version="6.*" />
<PackageReference Include="Regira.Web.Analytics" Version="6.*" />
<PackageReference Include="Regira.Web.Analytics.GeoIP2" Version="6.*" />
<PackageReference Include="Regira.Web.HTML.RazorEngineCore" Version="6.*" />
<PackageReference Include="Regira.Web.HTML.RazorLight" Version="6.*" />
<PackageReference Include="Regira.Web.HTML.RazorComponents" Version="6.*" />
<PackageReference Include="Regira.Web.Swagger" Version="6.*" />
HTML Template Parsing
IHtmlParser
Task<string> Parse<T>(string html, T model);
All three implementations share this interface.
HtmlTemplateParser (simple placeholder engine)
Replaces {key} tokens with the model's values. The model goes through the ISerializer first, so a key is the serialized name: Regira's JSON serializer camel-cases property names (Name → {name}, Customer.Name → {customer.name}) and keeps dictionary keys as written. A token with no value — a missing key, or a null the serializer leaves out — stays in the output as written.
A comment-marked block repeats its content once for each item of a collection, with that item's keys and a 1-based {rowNr}. Its name is letters only and starts lowercase. A block is not a condition: a true flag renders nothing. {key:format} formats a number inside a block; the optional valueConverter turns each top-level value into text (ToString() by default) and never sees block values.
<h1>{title}</h1>
<ul>
<li>{rowNr}. {title}: {price:0.00}</li>
</ul>
By default values are inserted as they are, so a value holding <b> comes out as markup. HtmlEncode = true encodes every text value, at the top level and in blocks; set it whenever the model carries user-supplied text. {key:raw} then writes a value unencoded.
ISerializer jsonSerializer = new JsonSerializer();
string template = "<p>Hello {name}!</p>";
var parser = new HtmlTemplateParser(jsonSerializer) { HtmlEncode = true };
string html = await parser.Parse(template, new { Name = "Alice" });
RazorEngineCore
Full Razor syntax. Strips @model directives and Layout blocks (not supported by the engine). Best for simple templates without layout inheritance.
By default it writes model values as they are, so a value holding <b> comes out as markup. HtmlEncode = true encodes every value a template writes with @, in text and in attribute values, the way RazorLight does; set it whenever the model carries user-supplied text. @Raw(value) then writes a value unencoded.
string razorTemplate = "<p>Hello @Model.Name</p>";
var model = new { Name = "Alice" };
IHtmlParser parser = new Regira.Web.HTML.RazorEngineCore.RazorTemplateParser(new()
{
HtmlEncode = true
});
string html = await parser.Parse(razorTemplate, model);
RazorLight
Full Razor syntax, with the @model directive compiled as written. Encodes every value a template writes with @; @Raw(value) writes a value unencoded. The host project needs <PreserveCompilationContext>true</PreserveCompilationContext>: without it the first Parse throws RazorLightException (Can't load metadata reference from the entry assembly).
string razorTemplate = "<p>Hello @Model.Name</p>";
var model = new { Name = "Alice" };
IHtmlParser parser = new Regira.Web.HTML.RazorLight.RazorTemplateParser();
string html = await parser.Parse(razorTemplate, model);
Compiled Razor templates
Both Razor parsers compile a template into an assembly that stays loaded until the process exits, and cache it by the template text for the whole process: each distinct template compiles once, whichever parser instance renders it, and later calls only render. Keep the template text fixed and pass the data as the model. Data concatenated into the text makes a new template on every call, which compiles every time and grows memory without bound.
RazorLight's Options.TemplateKey is [Obsolete] and ignored: a parser renders the template it is given.
A runtime Razor template is code. RazorLight and RazorEngineCore compile it as C# and run it in your process, with its file system, network and configuration; there is no sandbox. Let only trusted administrators edit one, keep user text in the model (where @ encodes it), and for templates end users write use HtmlTemplateParser with HtmlEncode = true, which replaces tokens and runs nothing. Each edited or previewed version compiles a new assembly that stays loaded until the process exits. A template that does not compile throws the engine's own exception (RazorLight's TemplateCompilationException, RazorEngineCore's RazorEngineCompilationException), which lists each error with its line.
Razor Components
Regira.Web.HTML.RazorComponents renders a Razor component — a .razor file compiled with the application — to HTML with ASP.NET Core's HtmlRenderer. It takes a component type rather than template text, so RazorComponentRenderer implements IHtmlComponentRenderer rather than IHtmlParser. A template is checked at build time, nothing compiles at runtime, and the package has no third-party dependency. Templates that change without a rebuild — stored in a database or deployed as files — need RazorLight instead, edited by trusted administrators only (Compiled Razor templates); templates end users edit belong to HtmlTemplateParser.
IHtmlComponentRenderer
Task<string> Render(Type componentType, IDictionary<string, object?>? parameters = null);
// Extensions
Task<string> Render<TComponent>(IDictionary<string, object?>? parameters = null);
Task<string> Render<TComponent, TModel>(TModel model); // sets the component's Model parameter
Each dictionary entry sets the component parameter of that name; the Type form serves a template picked at runtime.
Registration
using Regira.Web.HTML.Abstractions;
using Regira.Web.HTML.RazorComponents;
var services = new ServiceCollection();
services.AddTransient<IHtmlComponentRenderer, RazorComponentRenderer>();
Register it transient: the renderer takes the provider that resolves it, so @inject resolves from the request's scope. As a singleton it would hold the root provider, and a scoped service such as a DbContext fails. Without DI, new RazorComponentRenderer() renders any component that injects nothing.
A template
The model is a parameter named Model, which Render<TComponent, TModel> sets:
<h1>Invoice #@Model.Number</h1>
<p>Customer: @Model.CustomerName</p>
@code {
[Parameter, EditorRequired] public InvoiceDto Model { get; set; } = null!;
}
string html = await renderer.Render<InvoiceTemplate, InvoiceDto>(invoice);
A .cshtml template ports by replacing @model InvoiceDto with the [Parameter] property and @Raw(value) with @((MarkupString)value).
The .razor files compile in the consuming project, which needs the Razor SDK: Microsoft.NET.Sdk.Web has it, and a worker, console app or class library uses Microsoft.NET.Sdk.Razor. A project on the Razor SDK that also holds .cshtml template files for RazorLight or RazorEngineCore sets <EnableDefaultRazorGenerateItems>false</EnableDefaultRazorGenerateItems>, so the SDK leaves them as template text rather than taking them for MVC views. PreserveCompilationContext is not needed for the components; RazorLight needs it.
Rendering behaviour
- Encoding. Values are HTML-encoded;
@((MarkupString)value)writes markup. - Async.
OnInitializedAsyncandOnParametersSetAsyncare awaited before the HTML is returned. - Components. Child components and generic components (
@typeparam) render. - Layouts.
@layouthas no effect. A shared document frame is a component with aChildContentparameter that wraps the content. - HTML only. No
NavigationManager, no event handlers, no render modes, no JavaScript interop. - Culture. The caller's
CurrentCulture, soUseRequestLocalization()applies to the rendered HTML. - Whitespace. Whitespace between elements in code blocks is trimmed;
@preservewhitespace truekeeps it. - Exceptions pass through unwrapped: the template's own, and
InvalidOperationExceptionfor a parameter the component does not declare or an@injectservice the provider cannot resolve. - Memory. Each call renders on its own
HtmlRendererand disposes it, so nothing is retained between calls.
Common.Web Utilities
Exceptions and request culture
ASP.NET Core's own middleware covers both. AddProblemDetails() with UseExceptionHandler() logs an unhandled exception and answers a 500 problem response without its details; UseRequestLocalization() sets the request's culture from ?culture=, a cookie or Accept-Language, among the cultures the app supports.
var builder = WebApplication.CreateBuilder();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseRequestLocalization(options => options
.SetDefaultCulture("en")
.AddSupportedCultures("en", "nl-BE", "fr-BE")
.AddSupportedUICultures("en", "nl-BE", "fr-BE"));
// Request: GET /api/products?culture=nl-BE → sets nl-BE culture
RoutePrefixConvention
Apply a central route prefix to every controller. An absolute template (/x or ~/x, on a controller or an action) is not combined and skips the prefix: write the base into it.
var services = new ServiceCollection();
services.AddControllers(options =>
options.UseCentralRoutePrefix(new RouteAttribute("api/v1")));
TextPlainInputFormatter
Enables [FromBody] string binding for text/plain requests.
var services = new ServiceCollection();
services.AddControllers(options =>
options.InputFormatters.Insert(0, new TextPlainInputFormatter()));
ControllerExtensions, NamedFileResultExtensions and FormFileExtensions
// Return INamedFile as a download or inline
return this.File(namedFile, inline: true);
// The same from a minimal-API endpoint, as an IResult
return namedFile.ToFileResult(httpContext, inline: true);
// Read an upload as an INamedFile
var upload = formFile.ToNamedFile();
File()andToFileResult()answer 404 for a file without content, and sendX-Content-Type-Options: nosniffand, with every file but a PDF,Content-Security-Policy: sandbox, so a file served from the app's origin renders but runs no script, whatever its name or stored type. A PDF goes without: a sandbox keeps the browser's PDF viewer from loading. The sandbox is added to a policy the app already sent, not put in its place; a middleware that setsContent-Security-Policyonce the response starts (OnStarting) must append to the header too, or it replaces the sandbox.ToNamedFile()setsContentTypefrom the file name's extension (application/octet-streamwhen unknown), never from the type the client declared. Restrict uploads by extension where it matters.
RequestUtility
Extension methods on HttpRequest:
string url = Request.CurrentUrl();
Uri baseUrl = Request.GetBaseUrl();
Uri abs = Request.GetAbsoluteUrl("/images/logo.png");
Uri? referrer = Request.GetReferrer();
IPAddress? ip = Request.GetIPAddress();
Web.Swagger
Add JWT Bearer and/or API Key inputs to the Swagger UI:
var builder = WebApplication.CreateBuilder();
builder.Services.AddSwaggerGen(o =>
{
JwtAuthenticationExtensions.AddJwtAuthentication(o);
// or
ApiKeyAuthenticationExtensions.AddApiKeyAuthentication(o, parameterName: "X-Api-Key");
});
Make enums display as strings in Swagger:
var builder = WebApplication.CreateBuilder();
builder.Services.AddControllers().DisplayEnumAsString();
Overview
- Index — Overview, template engines, middleware, and Swagger
- Examples — HTML templating, exception handling, background tasks, Razor components
License
Apache License 2.0 — this package contains no license validation and no runtime limits. See LICENSE. A few companion packages are commercially licensed with a free tier; see the licensing overview.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
-
net10.0
- Regira.Common (>= 6.6.0)
-
net8.0
- Regira.Common (>= 6.6.0)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on Regira.Web:
| Package | Downloads |
|---|---|
|
Regira.Entities.Web
REST/CRUD Web API for Regira entities: list, search, filter, sort and paging endpoints, as EntityControllerBase controllers or mapped minimal-API endpoints (MapEntityEndpoints). Top-level web entry point — brings the DependencyInjection and EF Core packages transitively. Free tier included — a license key removes the free-tier limits. |
|
|
Regira.Security.Authentication.Web
ASP.NET Core authentication middleware and OpenAPI integration for Regira. |
|
|
Regira.Web.HTML.RazorEngineCore
Razor-based HTML template rendering using RazorEngineCore for Regira. |
|
|
Regira.Web.Swagger
Swagger/OpenAPI documentation extensions using Swashbuckle for Regira. |
|
|
Regira.Web.HTML.RazorLight
Razor-based HTML template rendering using RazorLight for Regira. |
GitHub repositories
This package is not used by any popular GitHub repositories.