WFC 2.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package WFC --version 2.2.0
                    
NuGet\Install-Package WFC -Version 2.2.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="WFC" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WFC" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="WFC" />
                    
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 WFC --version 2.2.0
                    
#r "nuget: WFC, 2.2.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 WFC@2.2.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=WFC&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=WFC&version=2.2.0
                    
Install as a Cake Tool

WebForms Core Technology

WebForms Core (WFC) is a revolutionary web technology for user interface management that combines a stateless architecture, lightweight string-based commands, an HTML-native structure, sequential DOM execution, and structural rendering capabilities into a unified model. It enables the dynamic control and modification of HTML elements through executable commands generated on the server or in WebAssembly. Developers can manage text, styles, attributes, states, and UI structure without relying on a standalone front-end framework.

Unlike web frameworks and tools based on data flow, WebForms Core is based on a command-driven flow and a stateless server architecture. It is available for a wide range of web programming languages, allowing developers to use the same programming model across different languages and platforms.

WebForms Core brings the desktop programming experience to the web. This was a vision pursued by some of the world's largest technology companies, yet none of them came close to achieving such an advanced model for web development. Elanat did. WebForms Core turns this vision into reality through a stateless, server-orchestrated UI architecture that allows developers to build dynamic web interfaces with the directness and control of desktop programming.

WebForms Core consists of two main components:

  1. Commander: The WebForms class used to define and generate commands
  2. Executor: The WebFormsJS library that receives and executes those commands in the browser

WebForms Core is a technology developed by Elanat.

How to Work with WebForms Core in C# (Razor Pages)

WebForms Core can be used directly from C# Razor Pages in ASP.NET Core. The WebForms class acts as the server-side Commander, allowing C# code to generate commands that WebFormsJS executes against the HTML DOM.

To use WebForms Core, first add the WFC package from NuGet to your project. Then create the following Razor Page in the Pages directory.

View File: Index.cshtml

@page
@model IndexModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>Using WebForms Core</title>
    <script type="module" src="/script/web-forms.js"></script>
</head>
<body>
    <form method="post" asp-page-handler="Submit">

        <label for="txt_Name">Your Name</label>
        <input name="txt_Name" id="txt_Name" type="text" />
        <br>
        <label for="txt_FontSize">Set Font Size</label>
        <input name="txt_FontSize" id="txt_FontSize" type="number" value="16" min="10" max="36" />
        <br>
        <label for="txt_BackgroundColor">Set Background Color</label>
        <input name="txt_BackgroundColor" id="txt_BackgroundColor" type="text" />
        <br>
        <input name="btn_SetBodyValue" type="submit" value="Click to send data" />
    </form>

    @Html.Raw(ViewData["WebForms"] ?? "")

</body>
</html>

C# Code: Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using WebFormsCore;

public class IndexModel : PageModel
{
    [BindProperty]
    public string txt_Name { get; set; }

    [BindProperty]
    public int txt_FontSize { get; set; } = 16;

    [BindProperty]
    public string txt_BackgroundColor { get; set; }

    [BindProperty]
    public string btn_SetBodyValue { get; set; }

    public IActionResult OnGet()
    {
        WebForms form = new WebForms();

        form.SetTextColor("(btn_SetBodyValue)", "green");

        ViewData["WebForms"] = form.ExportToHtmlComment();

        return Page();
    }

    public IActionResult OnPostSubmit()
    {
        if (!string.IsNullOrEmpty(btn_SetBodyValue))
        {
            WebForms form = new WebForms();

            form.SetFontSize("<form>", txt_FontSize);
            form.SetBackgroundColor("<form>", txt_BackgroundColor);
            form.SetDisabled("(btn_SetBodyValue)", true);

            form.AddTag("<form>", "h3");
            form.SetText("<h3>", "Welcome " + txt_Name + "!");

            return Content(form.Response(), "text/html");
        }

        return Page();
    }
}

How It Works

On the initial GET request, Razor Pages renders the HTML view normally. Because Razor Pages does not provide a direct mechanism for injecting arbitrary generated content from the PageModel into the rendered View, this example uses ViewData["WebForms"] to pass the generated WebForms Core response to the View.

The following code generates a WebForms Core response:

WebForms form = new WebForms();

form.SetTextColor("(btn_SetBodyValue)", "green");

ViewData["WebForms"] = form.ExportToHtmlComment();

ExportToHtmlComment() generates the same WebForms Core response produced by Response(), but wraps it in an HTML comment. The comment is therefore included in the HTML document sent by the server without becoming visible markup.

When the document loads, WebFormsJS detects the WebForms Core commands in the HTML comment and executes them against the DOM. In this example, the submit button is changed to green immediately after the document is loaded.

Client-side execution occurs immediately after the document loads; therefore, UI changes can take place so rapidly that the user may not notice the transition once the command reaches the WebFormsJS Executor.

Handling Form Submission

When the form is submitted, Razor Pages calls OnPostSubmit(). The PageModel receives the submitted values and uses the WebForms class to generate the required UI commands:

WebForms form = new WebForms();

form.SetFontSize("<form>", txt_FontSize);
form.SetBackgroundColor("<form>", txt_BackgroundColor);
form.SetDisabled("(btn_SetBodyValue)", true);

form.AddTag("<form>", "h3");
form.SetText("<h3>", "Welcome " + txt_Name + "!");

Instead of rendering the entire page again, the server returns only the generated WebForms Core response:

return Content(form.Response(), "text/html");

WebFormsJS receives this response and executes the commands against the existing DOM. The browser therefore keeps the current page structure and applies only the requested UI changes.

This illustrates the basic WebForms Core programming model in Razor Pages:

C# PageModel
     ↓
WebForms class
     ↓
WebForms Core Response
     ↓
WebFormsJS Executor
     ↓
Existing HTML DOM

The C# developer works with the WebForms programming model, while WebFormsJS handles the client-side DOM execution.

How to Work with WebForms Core in C# WebAssembly

WebForms Core can also be used with C# WebAssembly through the .NET WebCIL Container or AOT mode. In this model, C# code is compiled to WebAssembly and can execute inside the browser.

The WebForms Core WebForms class can be used directly inside the C# WebAssembly module. This allows C# WebAssembly methods to generate WebForms Core responses without directly manipulating the browser DOM. The generated responses are returned to WebFormsJS, which executes the commands against the existing HTML DOM.

First, create and publish a .NET WebCIL/AOT project containing the C# methods that will be executed in the WebAssembly environment.

The following example defines three exported methods:

using System.Runtime.InteropServices.JavaScript;
using WebFormsCore;

public partial class MyClass
{
    [JSExport]
    public static int Add(int a, int b)
    {
        return a + b;
    }

    [JSExport]
    public static string SetData(string inputPlace, string text, string backgroundColor, string fontSize)
    {
        WebForms form = new WebForms();

        form.SetText(inputPlace, text);
        form.SetBackgroundColor("-", backgroundColor);
        form.SetFontSize("-", fontSize);

        return form.Response();
    }

    [JSExport]
    public static string GetHtml()
    {
        return "<marquee>Tag From Wasm!</marquee>";
    }
}

public class Program
{
    public static void Main()
    {
    }
}

Methods that need to be called from the host application must be publicly accessible and exported from the WebCIL/AOT module using [JSExport].

After publishing the .NET WebCIL/AOT project, the generated WebAssembly and runtime files can be used by the WebForms Core application.

Calling C# WebAssembly from Server-Side Code

Server-side code can call exported C# WebAssembly methods through the WebForms Core C# execution model.

Note WebForms Core can be used independently within a WebAssembly environment. However, this example demonstrates how WebAssembly methods can be invoked through server-generated commands, allowing server-side code to orchestrate their execution in the browser.

The following CodeBehind framework controller demonstrates three operations:

using CodeBehind;

public partial class WasmCsharpController : CodeBehindController
{
    public void PageLoad(HttpContext context)
    {
        string WasmPath = "/web-assembly/csharp-publish/_framework/dotnet.js";
        //string WasmPath = "/web-assembly/csharp-publish/_framework/NativeWasmModule.wasm";

        WebForms form = new WebForms();

        form.AddText("<b>",
            Fetch.WasmMethod(
                WasmLanguage.CSharp,
                WasmPath,
                "MyClass.Add",
                [10000, 3]
            )
        );

        form.SetWasmEvent(
            "WasmEvent",
            HtmlEvent.OnClick,
            WasmLanguage.CSharp,
            WasmPath,
            "MyClass.SetData",
            ["h3Tag", "Text From Wasm", "lightgreen", "30px"]
        );

        form.SetWasmEvent(
            "WasmEventWithOutput",
            HtmlEvent.OnClick,
            WasmLanguage.CSharp,
            WasmPath,
            "MyClass.GetHtml",
            [],
            "WasmHtmlOutput"
        );

        Write(form.ExportToHtmlComment());
    }
}

Fetch.WasmMethod calls an exported C# method in the WebAssembly environment and returns its result to the WebForms Core execution flow.

For example:

Fetch.WasmMethod(
    WasmLanguage.CSharp,
    WasmPath,
    "MyClass.Add",
    [10000, 3]
)

calls MyClass.Add with 10000 and 3 and returns the resulting value. That value can then be used by the surrounding WebForms Core code.

SetWasmEvent can associate an exported C# WebAssembly method with a browser event. For example:

form.SetWasmEvent(
    "WasmEvent",
    HtmlEvent.OnClick,
    WasmLanguage.CSharp,
    WasmPath,
    "MyClass.SetData",
    ["h3Tag", "Text From Wasm", "lightgreen", "30px"]
);

When the WasmEvent button is clicked, the MyClass.SetData method is executed inside the C# WebAssembly environment.

The method creates a WebForms instance and generates a WebForms Core response:

WebForms form = new WebForms();

form.SetText(inputPlace, text);
form.SetBackgroundColor("-", backgroundColor);
form.SetFontSize("-", fontSize);

return form.Response();

The generated response does not directly modify the DOM from C#. Instead, it is returned to WebFormsJS, where the WebFormsJS Executor interprets and executes the generated commands against the h3Tag element.

The second SetWasmEvent associates the MyClass.GetHtml method with another browser event:

form.SetWasmEvent(
    "WasmEventWithOutput",
    HtmlEvent.OnClick,
    WasmLanguage.CSharp,
    WasmPath,
    "MyClass.GetHtml",
    [],
    "WasmHtmlOutput"
);

When the button is clicked, MyClass.GetHtml returns an HTML string, which is placed inside the WasmHtmlOutput element.

View

The CodeBehind controller can be used with the following view:

@page
@controller WasmCsharpController
@layout "/layout.aspx"
@{
    ViewData.Add("title","C# Wasm");
}
<h3>.NET WebCIL Container</h3>
<b>C# WASM Result: </b>
<br>
<button id="WasmEvent">Wasm Event</button>
<br>
<h3 id="h3Tag">Wasm Tag Changing!</h3>
<button id="WasmEventWithOutput">Wasm Event With Output</button>
<p id="WasmHtmlOutput">Wasm Html Output</p>

The first button executes MyClass.SetData in the C# WebAssembly environment. The method generates a WebForms Core response that changes the text, background color, and font size of the h3Tag element.

The second button executes MyClass.GetHtml and places its returned HTML inside the WasmHtmlOutput element.

C# WebAssembly and WebForms Core

C# WebAssembly does not directly manipulate the browser DOM in this model. Instead, it uses the same WebForms Core programming model to generate values or WebForms Core responses.

A C# WebAssembly method can therefore perform a computation and return a normal value, or create a WebForms instance and return a WebForms Core response.

When a WebForms Core response is returned, WebFormsJS receives the generated commands and executes them against the HTML DOM.

The execution flow for a WebForms Core response generated by C# WebAssembly is:

C# WebAssembly
       ↓
   WebForms
       ↓
WebForms Response
       ↓
WebFormsJS Executor
       ↓
   HTML DOM

When CodeBehind is responsible for invoking the WebAssembly method, the broader flow is:

CodeBehind
     ↓
C# WebAssembly
     ↓
  WebForms
     ↓
WebForms Response
     ↓
WebFormsJS Executor
     ↓
  HTML DOM

This allows developers to use the same WebForms programming model in C# WebAssembly that they use in server-side C# code. The C# code defines the required UI operations, WebForms generates the commands, and WebFormsJS performs the actual DOM execution in the browser.

The result is that C# WebAssembly can participate in dynamic WebForms Core interfaces without introducing a separate client-side UI framework or requiring the WebAssembly code to manipulate the DOM directly.

WebFormsJS

To use WebForms Core, in addition to the WebForms class, you must add the WebFormsJS script to the HTML <head> section, as WebFormsJS processes and applies server-generated UI updates on the client side.

The latest version of WebFormsJS can be installed or downloaded from the following sources:

Installation via Package

npm package: https://www.npmjs.com/package/webformsjs

CLI:

npm install webformsjs

Download / Copy the File

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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.
  • net7.0

    • No dependencies.

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
2.2.1 89 10/3/2026
2.2.0 88 10/2/2026
2.1.1 119 9/7/2026
2.1.0 110 9/3/2026
2.0.1 214 1/3/2026
2.0.0 181 1/2/2026