Vitraux 1.0.2-rc

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

Vitraux

Map your .NET ViewModels to HTML in WebAssembly

Banner

Introduction

Vitraux is a .NET library for manipulating the HTML DOM in WebAssembly applications.
Using a declarative approach, it maps .NET ViewModels directly to standard HTML elements, maintaining a clear separation of concerns between frontend and backend. This makes your code easier to maintain, more readable, and highly scalable.

Mapping


Key Benefits

  • Clean HTML and C#: No need for custom components or mixing .NET logic with HTML. Your frontend remains pure HTML5 and your backend pure .NET.

  • True Decoupling: Keeps business logic (backend) and presentation (frontend) fully separated, making collaboration and maintenance easier.

  • Declarative Mapping: Define the mapping between ViewModels and HTML elements in a simple, expressive way.

  • Easy Integration: Just define your mappings and call an update method. Everything else is handled automatically.

  • Efficient DOM Updates: Works with DOM objects in memory as much as possible, updating the UI only when strictly necessary for optimal performance.

  • Compatible and Scalable: Works with anything from vanilla HTML and Web Components to any frontend tool that outputs HTML.

  • HTML Modularization: Lets you break your HTML into fragments stored in templates or external URIs, which you can design and structure however you like.


Features

  • Change Tracking: Sends and updates only the data that actually changed since the last update, minimizing data transfer and avoiding unnecessary re-renders.

  • Flexible Element Selection Strategies: Multiple ways to select HTML elements, adaptable to any view structure.

  • Custom JavaScript Function Mapping: Call your own JavaScript functions in response to ViewModel changes.

  • Modular Mapping: Split your mapping into sub-mappings for better readability and reuse.

  • Auto-Generated Function Caching: Initialization and update functions generated by Vitraux can be cached for faster load times.

  • Shadow DOM Support: Optionally encapsulate styles and structure using Shadow DOM, depending on project needs.


Getting Started

  1. Create a Blazor WebAssembly Standalone Project
    Use Visual Studio and disable the “Include sample pages” option, or create it via the .NET CLI:

    dotnet new blazorwasm --empty -o MyProject
    
    
  2. Remove all .razor files
    Delete all .razor files from your solution so it’s clean and free of Blazor pages or components.

    Remove .razor Files

  3. Remove root component code from Main()
    Remove any root component registration and rendering from Main() — Vitraux doesn’t use them.

    Remove Root Components

  4. Install the Vitraux NuGet package

  5. Add the Vitraux JavaScript file
    Place vitraux-<version>-min.js anywhere in your site’s folder structure. There’s no required location
    — just ensure your HTML references the correct path.

  6. Include the JavaScript references in your HTML
    Add the vitraux-<version>-min.js reference in <head> or before the closing </body>.
    The _framework/blazor.webassembly.js reference must be placed at the end of <body>:

    <script src="js/vitraux-<version>-min.js"></script>
    ...
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    
    
  7. Add your C# code and a minimal configuration example

    // PetOwner.cs
    public record class PetOwner
    {
       public int Id { get; init; }
       public string Name { get; init; } = string.Empty;
       public string Address { get; init; } = string.Empty;
       public string? PhoneNumber { get; init; }
       public string HtmlComments { get; init; } = string.Empty;
       public IEnumerable<Pet> Pets { get; init; } = Enumerable.Empty<Pet>();
    }
    
    // Pet.cs
    public record class Pet
    {
       public string Name { get; init; } = string.Empty;
       public DateTime DateOfBirth { get; init; }
    }
    
    // PetOwnerConfiguration.cs
    public class PetOwnerConfiguration : IModelConfiguration<PetOwner>
    {
       public ConfigurationBehavior ConfigurationBehavior { get; } = new()
       {
          QueryElementStrategy = QueryElementStrategy.OnlyOnceAtStart,
          TrackChanges = true,
          VMUpdateFunctionCaching = VMUpdateFunctionCaching.ByVersion("test 1.0")
       };
    
       public ModelMappingData ConfigureMapping(IModelMapper<PetOwner> modelMapper)
          => modelMapper
                .MapValue(po => po.Name).ToElements.ById("petowner-name").ToContent
                .MapValue(po => po.Address).ToElements.ById("petowner-address").ToContent
                .MapValue(po => po.PhoneNumber).ToElements.ById("petowner-phone-number").ToContent
                .MapValue(po => po.HtmlComments).ToElements.ByQuery(".comments").ToHtml
                .MapCollection(po => po.Pets)
                   .ToTables.ById("petowner-pets")
                   .PopulatingRows.ToTBody(0).FromTemplate("petowner-pet-row")
                      .MapValue(pet => pet.Name).ToElements.ByQuery("[data-id='pet-name']").ToContent
                      .MapValue(pet => pet.DateOfBirth).ToElements.ByQuery("[data-id='pet-date-of-birth']").ToContent
                   .EndCollection
                .EndCollection
                .Data;
    }
    
    // Program.cs
    using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
    using Vitraux;
    using System.Runtime.InteropServices.JavaScript;
    
    public partial class Program
    {
       private static IViewUpdater<PetOwner> _petownerViewUpdater = default!;
    
       public static async Task Main(string[] args)
       {
          var builder = WebAssemblyHostBuilder.CreateDefault(args);
    
          _ = builder.Services
                .AddVitraux() //add Vitraux
                .AddConfiguration(() => new VitrauxConfiguration { UseShadowDom = true }) //add a configuration (optional)
                .AddModelConfiguration<PetOwner, PetOwnerConfiguration>(); //add the model configuration
    
          await using var host = builder.Build();
    
          await host.Services.BuildVitraux(); //Build Vitraux
    
          _petownerViewUpdater = host.Services.GetRequiredService<IViewUpdater<PetOwner>>(); //Get your view updater
    
          await host.RunAsync();
       }
    
       [JSExport]
       public static async Task GetPetOwner()
       {
          var petOwner = new PetOwner
          {
                Id = 1,
                Name = "Juan Pérez",
                Address = "Av. Siempre Viva 742",
                PhoneNumber = "+54 9 11 1234-5678",
                HtmlComments = "<b>Cliente VIP</b>",
                Pets = new[]
                {
                   new Pet { Name = "Boby", DateOfBirth = new DateTime(2021, 5, 1) },
                   new Pet { Name = "Miau", DateOfBirth = new DateTime(2019, 9, 14) }
                }
          };
    
          await _petownerViewUpdater.Update(petOwner); //Update the UI
       }
    }
    
    
  8. Full HTML Example

    <!DOCTYPE html>
    <html lang="en">
    <head>
       <meta charset="utf-8" />
       <title>Vitraux Example</title>
       <link rel="stylesheet" href="styles.css" />
       <script src="js/vitraux.js"></script>
       <script>
          addEventListener("DOMContentLoaded", async () => {
                await Blazor.start();
                const petOwnerWasm = await getPetOwnerWasm();
                await petOwnerWasm.GetPetOwner();
    
                async function getPetOwnerWasm() {
                   const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
                   const exports = await getAssemblyExports("YourProject.dll");
                   return exports.YourNamespace.Program;
                }
          });
       </script>
    </head>
    <body>
       <h1>Petowner Example</h1>
       <div class="info-section">
          <div>Owner Information</div>
          <div id="petowner-name"></div>
          <div id="petowner-address"></div>
          <div id="petowner-phone-number"></div>
       </div>
       <div class="info-section">
          <div>Pets</div>
          <table id="petowner-pets">
                <thead>
                   <tr>
                      <th>Name</th>
                      <th>Date of Birth</th>
                   </tr>
                </thead>
                <tbody></tbody>
          </table>
       </div>
       <div class="info-section">
          <div>Comments</div>
          <div class="comments"></div>
       </div>
    
       <template id="petowner-pet-row">
          <tr>
                <td data-id="pet-name"></td>
                <td data-id="pet-date-of-birth"></td>
          </tr>
       </template>
    
       <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    </body>
    </html>
    
    
  9. For a complete breakdown of features and technical details, see the Manual de Referencia.


How It Works

Vitraux uses declarative mapping to connect .NET ViewModels to standard HTML elements in WebAssembly applications. When you need to update the UI, you call an update method in .NET, which sends the data to the browser. Vitraux then runs an automatically generated JavaScript function to update the DOM, keeping your view in sync with your data model.


Installation

Install the package from NuGet


Contributing

Contributions are welcome! If you have ideas, find bugs, or want to collaborate, feel free to open an Issue or Pull Request.


License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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.0.2-rc 136 8/14/2025