ToonNet.AspNetCore
4.0.0
dotnet add package ToonNet.AspNetCore --version 4.0.0
NuGet\Install-Package ToonNet.AspNetCore -Version 4.0.0
<PackageReference Include="ToonNet.AspNetCore" Version="4.0.0" />
<PackageVersion Include="ToonNet.AspNetCore" Version="4.0.0" />
<PackageReference Include="ToonNet.AspNetCore" />
paket add ToonNet.AspNetCore --version 4.0.0
#r "nuget: ToonNet.AspNetCore, 4.0.0"
#:package ToonNet.AspNetCore@4.0.0
#addin nuget:?package=ToonNet.AspNetCore&version=4.0.0
#tool nuget:?package=ToonNet.AspNetCore&version=4.0.0
ToonNet.AspNetCore
ASP.NET Core integration for ToonNet serialization
๐ฆ What is ToonNet.AspNetCore?
ToonNet.AspNetCore provides seamless integration of ToonNet serialization with ASP.NET Core:
- โ
Dependency Injection - Register
ToonEncoderand options - โ Configuration Binding - Load settings from appsettings.json
- โ Options Validation - Fail-fast on invalid configuration
- โ TOON Configuration Provider - Read TOON files as configuration source
- โ
MVC Ready - Foundation for the
ToonNet.AspNetCore.Mvcformatters
Perfect for:
- ๐ Web APIs - Shared options for TOON responses (formatters in
ToonNet.AspNetCore.Mvc) - โ๏ธ Configuration - Load TOON config files
- ๐ง DI Integration - Inject
ToonEncoderand options into services - ๐ Options Pattern - Configure ToonNet via appsettings.json
๐ Quick Start
Installation
# Core package (required)
dotnet add package ToonNet.Core
# ASP.NET Core integration
dotnet add package ToonNet.AspNetCore
# For MVC formatters (optional)
dotnet add package ToonNet.AspNetCore.Mvc
Basic Setup - Default Options
using ToonNet.AspNetCore.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register ToonNet services with default options
builder.Services.AddToonNet();
var app = builder.Build();
app.Run();
This registers:
ToonEncoder(singleton)ToonOptions(IOptions<ToonOptions>)ToonSerializerOptions(IOptions<ToonSerializerOptions>), whoseToonOptionsis the registeredToonOptionsunless a serializer options delegate sets another instance
โ๏ธ Configuration
Using appsettings.json (Recommended)
appsettings.json:
{
"ToonNet": {
"ToonOptions": {
"IndentSize": 2,
"MaxDepth": 100,
"Delimiter": ",",
"StrictMode": true,
"AllowExtendedLimits": false
},
"ToonSerializerOptions": {
"IncludeReadOnlyProperties": false,
"MaxDepth": 100,
"AllowExtendedLimits": false
}
}
}
Only the keys shown in the tables below are read. ToonSerializerOptions also accepts IgnoreNullValues and
PropertyNamingPolicy (Default, CamelCase, SnakeCase, LowerCase; any other value fails at startup). Use a
different root section name with
AddToonNet(builder.Configuration, "MySection").
Program.cs:
using ToonNet.AspNetCore.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Bind configuration from appsettings.json
builder.Services.AddToonNet(builder.Configuration);
var app = builder.Build();
app.Run();
Using Delegate Configuration
builder.Services.AddToonNet(toonOptions =>
{
toonOptions.IndentSize = 4;
toonOptions.MaxDepth = 50;
}, serializerOptions =>
{
serializerOptions.IncludeReadOnlyProperties = false;
serializerOptions.MaxDepth = 100;
});
// Only the serializer options
builder.Services.AddToonNet(serializerOptions => serializerOptions.PropertyNamingPolicy = PropertyNamingPolicy.CamelCase);
Calling AddToonNet more than once is safe: the delegates add up, and the services and validation are registered once.
Hybrid Approach (Configuration + Delegate)
// Load from config, then override specific values (Configure runs after the configuration binding)
builder.Services.AddToonNet(builder.Configuration);
builder.Services.Configure<ToonOptions>(toonOptions =>
{
toonOptions.IndentSize = 4;
});
builder.Services.Configure<ToonSerializerOptions>(serializerOptions =>
{
serializerOptions.IncludeReadOnlyProperties = true;
});
๐ Configuration Options
ToonOptions
Controls TOON format encoding behavior:
| Option | Type | Default | Description |
|---|---|---|---|
IndentSize |
int |
2 |
Number of spaces per indentation level (1-100) |
MaxDepth |
int |
100 |
Maximum nesting depth when encoding and parsing; deeper input is rejected with ToonParseException |
Delimiter |
char |
, |
Document delimiter: ,, tab or \| (configuration also accepts comma, tab, pipe) |
StrictMode |
bool |
true |
Enable strict parsing rules (e.g. array length checks) |
AllowExtendedLimits |
bool |
false |
Allow MaxDepth above 200 (up to 1000) |
ToonSerializerOptions
Controls C# object serialization behavior:
| Option | Type | Default | Description |
|---|---|---|---|
IgnoreNullValues |
bool |
false |
Skip properties whose value is null |
IncludeReadOnlyProperties |
bool |
true |
Include read-only properties when serializing (also those whose setter is not public, unless [ToonInclude]) |
PropertyNamingPolicy |
PropertyNamingPolicy |
Default |
Key naming: Default, CamelCase, SnakeCase, LowerCase |
PropertyNameCaseInsensitive |
bool |
false |
Match keys to property names ignoring case when reading |
UnmappedMemberHandling |
ToonUnmappedMemberHandling |
Skip |
Disallow: a key that matches no property is an error |
RespectRequiredMembers |
bool |
true |
A missing key for a C# required property is an error (false before 4.0) |
SerializeRuntimeTypes |
bool |
false |
Write objects with their runtime type instead of their declared type (true before 4.0) |
MaxDepth |
int |
100 |
Maximum object graph depth |
AllowExtendedLimits |
bool |
false |
Allow MaxDepth above 200 (up to 1000) |
Untrusted input: parsing enforces
ToonOptions.MaxDepthand also checks the remaining stack space, so hostile, deeply nested input fails with aToonParseExceptioninstead of crashing the process. KeepAllowExtendedLimitsoff andStrictModeon for input you don't control.SerializeRuntimeTypes = truewrites the members of derived types too (an entity in a property of a summary type writes all of the entity's properties), which can put data in responses that the declared type leaves out.
๐ฏ Usage Patterns
Pattern 1: Inject ToonEncoder
ToonEncoder is registered as a singleton with the configured ToonOptions and is safe to use from concurrent requests. There is no injectable parser; parse
with ToonDocument.Parse and the injected options:
using Microsoft.Extensions.Options;
using ToonNet.Core;
using ToonNet.Core.Encoding;
using ToonNet.Core.Models;
public class ToonService
{
private readonly ToonEncoder _encoder;
private readonly ToonOptions _options;
private readonly ILogger<ToonService> _logger;
public ToonService(
ToonEncoder encoder,
IOptions<ToonOptions> options,
ILogger<ToonService> logger)
{
_encoder = encoder;
_options = options.Value;
_logger = logger;
}
public ToonDocument ParseToon(string toonString)
{
try
{
return ToonDocument.Parse(toonString, _options);
}
catch (ToonParseException ex)
{
_logger.LogError(ex, "Failed to parse TOON");
throw;
}
}
public string EncodeToon(ToonDocument document)
{
return _encoder.Encode(document);
}
}
// Register service
builder.Services.AddScoped<ToonService>();
Pattern 2: Inject Options
using Microsoft.Extensions.Options;
using ToonNet.Core;
using ToonNet.Core.Serialization;
public class ConfigAnalyzer
{
private readonly ToonOptions _toonOptions;
private readonly ToonSerializerOptions _serializerOptions;
public ConfigAnalyzer(
IOptions<ToonOptions> toonOptions,
IOptions<ToonSerializerOptions> serializerOptions)
{
_toonOptions = toonOptions.Value;
_serializerOptions = serializerOptions.Value;
}
public void LogConfiguration()
{
Console.WriteLine($"Indent Size: {_toonOptions.IndentSize}");
Console.WriteLine($"Max Depth: {_toonOptions.MaxDepth}");
Console.WriteLine($"Include Read-Only: {_serializerOptions.IncludeReadOnlyProperties}");
}
}
Pattern 3: Use with ToonSerializer
using ToonNet.Core.Serialization;
using Microsoft.Extensions.Options;
public class DataService
{
private readonly ToonSerializerOptions _options;
public DataService(IOptions<ToonSerializerOptions> options)
{
_options = options.Value;
}
public string SerializeData<T>(T data)
{
// Use configured options
return ToonSerializer.Serialize(data, _options);
}
public T DeserializeData<T>(string toonString)
{
return ToonSerializer.Deserialize<T>(toonString, _options);
}
}
๐ TOON Configuration Provider
Load TOON files as ASP.NET Core configuration sources:
Create TOON Configuration File
appsettings.toon:
Database:
ConnectionString: Server=localhost;Database=mydb
Timeout: 30
EnableRetry: true
Logging:
Level: Information
Console:
Enabled: true
File:
Path: logs/app.log
MaxSize: 10485760
Features:
EnableCache: true
CacheExpiry: 3600
Register TOON Configuration Provider
var builder = WebApplication.CreateBuilder(args);
// Add TOON file as configuration source (using ToonNet.AspNetCore.Configuration;)
builder.Configuration.AddToonFile("appsettings.toon", optional: false, reloadOnChange: true);
// Register ToonNet services
builder.Services.AddToonNet(builder.Configuration);
var app = builder.Build();
// Access configuration
var connectionString = builder.Configuration["Database:ConnectionString"];
var logLevel = builder.Configuration["Logging:Level"];
Configuration Provider Features
// Multiple TOON files
builder.Configuration
.AddToonFile("appsettings.toon")
.AddToonFile($"appsettings.{builder.Environment.EnvironmentName}.toon", optional: true);
// With environment variables
builder.Configuration
.AddToonFile("config.toon")
.AddEnvironmentVariables();
// Reload on change
builder.Configuration.AddToonFile(
"settings.toon",
optional: false,
reloadOnChange: true // Auto-reload when file changes
);
// Custom parsing options (e.g. non-strict mode, for files you control)
builder.Configuration.AddToonFile("legacy.toon", optional: true, reloadOnChange: false,
options: new ToonOptions { StrictMode = false });
Nested objects become Section:Key paths and array items become index keys (Items:0, Items:1). Values are stored as
strings: booleans become True/False, and numbers keep their exact value in canonical TOON form (spec ยง2), so
12345678901234567890 stays as written while 1.0 becomes 1 and 1.50 becomes 1.5; quote a value (Version: "1.0")
to keep its text exactly. AddToonFile accepts relative and absolute paths. A file that is not valid TOON throws a
FormatException.
โ Validation
ToonNet.AspNetCore uses Options Validation to ensure configuration is valid:
Automatic Validation
// Validation happens at startup
builder.Services.AddToonNet(builder.Configuration);
// If configuration is invalid, app will fail to start with clear error message
Custom Validation
AddToonNet returns the IServiceCollection; add extra rules through the options builder:
builder.Services.AddToonNet(builder.Configuration);
builder.Services.AddOptions<ToonOptions>()
.Validate(options => options.IndentSize <= 8, "IndentSize must not exceed 8")
.ValidateOnStart();
Validation Rules (Built-in)
IndentSize: Must be between 1 and 100MaxDepth: Must be 1-200 (or 1-1000 ifAllowExtendedLimits = true)Delimiter: Must be comma, tab or pipe
๐ Thread-Safety
ToonSerializermethods are safe to call concurrently across threads.- A
ToonEncoderinstance keeps no per-call state and can be shared across threads (it is registered as a singleton byAddToonNet). - Shared metadata/name caches use
ConcurrentDictionaryfor concurrent access. - Cache entries are created on demand and retained for the process lifetime (no eviction).
- Do not mutate a single
ToonSerializerOptionsinstance concurrently across threads.
๐ Related Packages
Core:
ToonNet.Core- Core serialization (required)
Extensions:
ToonNet.Extensions.Json- JSON โ TOON conversionToonNet.Extensions.Yaml- YAML โ TOON conversion
Web Integration:
ToonNet.AspNetCore.Mvc- MVC input/output formatters
Development:
ToonNet.Demo- Sample applicationsToonNet.Tests- Test suite
๐ Documentation
- Main Documentation - Complete ToonNet guide
- API Guide - Detailed API reference
- Samples - Real-world examples
๐งช Testing
# Run ASP.NET Core integration tests
dotnet test tests/ToonNet.Tests --filter "FullyQualifiedName~ToonNet.Tests.AspNetCore"
๐ Requirements
- .NET 8.0 or later
- ASP.NET Core 8.0+
- ToonNet.Core
๐ License
MIT License - See LICENSE file for details.
๐ค Contributing
Contributions welcome! Please read CONTRIBUTING.md first.
Part of the ToonNet serialization library family.
| 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
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.FileExtensions (>= 8.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.FileProviders.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- ToonNet.Core (>= 4.0.0)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.FileExtensions (>= 8.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.FileProviders.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- ToonNet.Core (>= 4.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ToonNet.AspNetCore:
| Package | Downloads |
|---|---|
|
ToonNet.AspNetCore.Mvc
ASP.NET Core MVC integration for ToonNet. Provides input/output formatters for TOON format support in MVC controllers and Web APIs. |
GitHub repositories
This package is not used by any popular GitHub repositories.