ToonNet.AspNetCore.Mvc 1.4.0

dotnet add package ToonNet.AspNetCore.Mvc --version 1.4.0
                    
NuGet\Install-Package ToonNet.AspNetCore.Mvc -Version 1.4.0
                    
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="ToonNet.AspNetCore.Mvc" Version="1.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToonNet.AspNetCore.Mvc" Version="1.4.0" />
                    
Directory.Packages.props
<PackageReference Include="ToonNet.AspNetCore.Mvc" />
                    
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 ToonNet.AspNetCore.Mvc --version 1.4.0
                    
#r "nuget: ToonNet.AspNetCore.Mvc, 1.4.0"
                    
#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 ToonNet.AspNetCore.Mvc@1.4.0
                    
#: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=ToonNet.AspNetCore.Mvc&version=1.4.0
                    
Install as a Cake Addin
#tool nuget:?package=ToonNet.AspNetCore.Mvc&version=1.4.0
                    
Install as a Cake Tool

ToonNet.AspNetCore.Mvc

MVC input/output formatters for TOON format

.NET NuGet Downloads Status


📦 What is ToonNet.AspNetCore.Mvc?

ToonNet.AspNetCore.Mvc provides MVC input/output formatters for serving and accepting TOON format in ASP.NET Core APIs:

  • Input Formatter - Accept TOON in request body
  • Output Formatter - Serve TOON in response body
  • Content Negotiation - Accept: application/toon support
  • Model Binding - Automatic TOON → C# object conversion
  • ToonResult - Return TOON responses from actions

Perfect for:

  • 🌐 REST APIs - Serve TOON alongside JSON
  • 📊 Content Negotiation - Let clients choose format
  • 🤖 AI/LLM APIs - Token-efficient responses
  • 🔧 Flexible APIs - Support multiple formats

🚀 Quick Start

Installation

# Core packages (required)
dotnet add package ToonNet.Core
dotnet add package ToonNet.AspNetCore

# MVC formatters
dotnet add package ToonNet.AspNetCore.Mvc

Basic Setup

using ToonNet.AspNetCore;
using ToonNet.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

// Add ToonNet services
builder.Services.AddToon();

// Add MVC with TOON formatters
builder.Services.AddControllers()
    .AddToonFormatters();

var app = builder.Build();
app.MapControllers();
app.Run();

📖 Usage

Example 1: Content Negotiation

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public ActionResult<List<Product>> GetProducts()
    {
        var products = new List<Product>
        {
            new() { Id = 1, Name = "Laptop", Price = 1299.99m },
            new() { Id = 2, Name = "Mouse", Price = 29.99m },
            new() { Id = 3, Name = "Keyboard", Price = 89.99m }
        };

        // Automatic format negotiation based on Accept header
        return Ok(products);
    }
}

// Client requests:
// GET /api/products
// Accept: application/json  → Returns JSON
// Accept: application/toon  → Returns TOON
// Accept: */*               → Returns default format

TOON Response:

products[3]:
  - Id: 1
    Name: Laptop
    Price: 1299.99
  - Id: 2
    Name: Mouse
    Price: 29.99
  - Id: 3
    Name: Keyboard
    Price: 89.99

Example 2: Accept TOON Input

[HttpPost]
public ActionResult<Product> CreateProduct([FromBody] Product product)
{
    // Accepts both JSON and TOON based on Content-Type header
    // Content-Type: application/json  → Parses as JSON
    // Content-Type: application/toon  → Parses as TOON
    
    // Validate and save...
    return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

TOON Request Body:

Name: Gaming Mouse
Price: 59.99
InStock: true
Category: Electronics

Example 3: Explicit TOON Response

using ToonNet.AspNetCore.Mvc.Http;

[HttpGet("{id}")]
public IActionResult GetProduct(int id)
{
    var product = _repository.GetById(id);
    if (product == null)
        return NotFound();

    // Explicitly return TOON format
    return new ToonResult(product);
}

Example 4: Nested Objects

public class Order
{
    public int Id { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }
    public decimal Total { get; set; }
}

[HttpGet("orders/{id}")]
public ActionResult<Order> GetOrder(int id)
{
    var order = _orderService.GetById(id);
    return Ok(order);
}

TOON Response:

Id: 12345
Customer:
  Name: Alice Johnson
  Email: alice@example.com
Items[2]:
  - ProductName: Laptop
    Quantity: 1
    Price: 1299.99
  - ProductName: Mouse
    Quantity: 2
    Price: 29.99
Total: 1359.97

⚙️ Configuration

Custom Formatter Options

builder.Services.AddControllers()
    .AddToonFormatters(options =>
    {
        options.IndentSize = 4;
        options.PreferInlineArrays = true;
        options.MaxDepth = 100;
    });

Formatter Priority

builder.Services.AddControllers(options =>
{
    // Add TOON as preferred format
    options.RespectBrowserAcceptHeader = true;
    options.ReturnHttpNotAcceptable = true;
})
.AddToonFormatters();

Media Type Mappings

TOON formatters register these media types:

  • application/toon
  • text/toon
  • application/x-toon

📊 API Reference

ToonInputFormatter

Deserializes TOON request bodies to C# objects:

// Automatically registered with AddToonFormatters()
// Handles Content-Type: application/toon

ToonOutputFormatter

Serializes C# objects to TOON response bodies:

// Automatically registered with AddToonFormatters()
// Handles Accept: application/toon

ToonResult

Explicit TOON response result:

public class ToonResult : IActionResult
{
    public ToonResult(object value)
    public ToonResult(object value, ToonSerializerOptions options)
    
    public Task ExecuteResultAsync(ActionContext context)
}

// Usage:
return new ToonResult(data);
return new ToonResult(data, customOptions);

🔒 Thread-Safety

  • ToonSerializer methods are safe to call concurrently across threads.
  • Shared metadata/name caches use ConcurrentDictionary for concurrent access.
  • Cache entries are created on demand and retained for the process lifetime (no eviction).
  • Do not mutate a single ToonSerializerOptions instance concurrently across threads.

🎯 Real-World Examples

Example 1: AI/LLM API Endpoint

[HttpGet("context")]
[Produces("application/toon", "application/json")]
public ActionResult<UserContext> GetUserContext(int userId)
{
    var context = new UserContext
    {
        Name = "Alice",
        Age = 28,
        Interests = new[] { "AI", "Coding", "Gaming" },
        RecentPurchases = _purchaseService.GetRecent(userId, 10)
    };

    // LLM clients request with Accept: application/toon for fewer tokens
    return Ok(context);
}

Example 2: Batch Operations

[HttpPost("batch")]
[Consumes("application/toon")]
public ActionResult<BatchResult> ProcessBatch([FromBody] List<Product> products)
{
    // Client sends TOON (smaller payload)
    var results = _productService.BulkInsert(products);
    return Ok(results);
}

// Request (TOON - more compact):
// products[3]:
//   - Name: Item1, Price: 10.00
//   - Name: Item2, Price: 20.00
//   - Name: Item3, Price: 30.00

Example 3: Configuration API

[HttpPut("config")]
public async Task<IActionResult> UpdateConfig([FromBody] AppConfig config)
{
    // Accepts both JSON and TOON
    await _configService.UpdateAsync(config);
    
    // Return TOON for readability
    return new ToonResult(config);
}

🔍 Testing

Testing with WebApplicationFactory

using Microsoft.AspNetCore.Mvc.Testing;

public class ToonFormatterTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;

    public ToonFormatterTests(WebApplicationFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task GetProducts_WithToonAccept_ReturnsToon()
    {
        // Arrange
        _client.DefaultRequestHeaders.Add("Accept", "application/toon");

        // Act
        var response = await _client.GetAsync("/api/products");

        // Assert
        response.EnsureSuccessStatusCode();
        Assert.Equal("application/toon", response.Content.Headers.ContentType.MediaType);
        
        var toon = await response.Content.ReadAsStringAsync();
        Assert.Contains("Name:", toon);
        Assert.Contains("Price:", toon);
    }

    [Fact]
    public async Task PostProduct_WithToonContent_Success()
    {
        // Arrange
        var toonContent = """
            Name: Test Product
            Price: 99.99
            InStock: true
            """;
        
        var content = new StringContent(toonContent, Encoding.UTF8, "application/toon");

        // Act
        var response = await _client.PostAsync("/api/products", content);

        // Assert
        response.EnsureSuccessStatusCode();
    }
}

Core:

Extensions:

Development:


📚 Documentation


📋 Requirements

  • .NET 8.0 or later
  • ASP.NET Core MVC 8.0+
  • ToonNet.Core
  • ToonNet.AspNetCore

📄 License

MIT License - See LICENSE file for details.


🤝 Contributing

Contributions welcome! Please read CONTRIBUTING.md first.


Part of the ToonNet serialization library family.

Product 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 was computed.  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.4.0 100 2/8/2026
1.3.0 94 2/4/2026
1.2.0 100 2/1/2026
1.1.0 99 1/28/2026
1.0.0 101 1/12/2026

v1.4.0: Updated to support ToonNet.Core 1.4.0 streaming features.