<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Elanat Framework</title>
    <description>The latest articles on DEV Community by Elanat Framework (@elanatframework).</description>
    <link>https://dev.to/elanatframework</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1106033%2Fd06a8be3-da79-4eeb-ad53-1401e09446cc.png</url>
      <title>DEV Community: Elanat Framework</title>
      <link>https://dev.to/elanatframework</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elanatframework"/>
    <language>en</language>
    <item>
      <title>Return template</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 05 Nov 2026 21:25:53 +0000</pubDate>
      <link>https://dev.to/elanatframework/return-template-25fc</link>
      <guid>https://dev.to/elanatframework/return-template-25fc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A well-structured web application should keep presentation and application logic separate. The View should primarily describe the HTML structure, while server-side code handles data processing and application behavior.&lt;/p&gt;

&lt;p&gt;CodeBehind is a .NET Core framework built around this separation. Unlike approaches that embed server-side logic directly into HTML, CodeBehind provides mechanisms for keeping the View focused on presentation.&lt;/p&gt;

&lt;p&gt;However, loops and conditional statements can make this separation difficult to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge of Dynamic Content
&lt;/h2&gt;

&lt;p&gt;Consider a navigation menu generated from a collection of pages. In Razor, the implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="navigation"&amp;gt;
    @foreach (var page in Model.Pages)
    {
        &amp;lt;a href="@page.Path"&amp;gt;@page.Title&amp;lt;/a&amp;gt;
    }
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this syntax is convenient, the View now contains both HTML and server-side control flow.&lt;/p&gt;

&lt;p&gt;Another approach is to generate the HTML entirely in the Controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MenuHtml&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;div class='navigation'&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MenuHtml&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;$"&amp;lt;a href='&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/a&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MenuHtml&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;/div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This moves the logic out of the View, but makes HTML structures harder to read and maintain in server-side code.&lt;/p&gt;

&lt;p&gt;CodeBehind addresses this problem through Return Templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Return Templates
&lt;/h2&gt;

&lt;p&gt;Return Templates allow developers to define HTML structures separately from the loops and conditions that generate them.&lt;/p&gt;

&lt;p&gt;The main idea is simple: a Return Template is initially assigned to a template variable. When the template is processed, its returned content replaces that variable. This process can happen recursively, allowing multiple template levels to be resolved.&lt;/p&gt;

&lt;p&gt;CodeBehind supports two template syntaxes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Razor Syntax&lt;/li&gt;
&lt;li&gt;Standard Syntax&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each syntax has its own template notation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Example
&lt;/h2&gt;

&lt;p&gt;Let's create a navigation menu using Razor Syntax.&lt;/p&gt;

&lt;p&gt;First, define the HTML structure in the View:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="navigation"&amp;gt;
    @#Menu={&amp;lt;a href="@#PageUrl"&amp;gt;@#PageTitle&amp;lt;/a&amp;gt;}
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define the Return Template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@#Menu{
    @foreach (PageItem page in model.PageItemList)
    {
        @#Menu
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, define the values used by each menu item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@#PageTitle{@page.Title}
@#PageUrl{@(((page.Path == "main") ? "/" : page.Path))}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The processing takes place in multiple stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1:&lt;/strong&gt; The Return Template generates the repeated menu structure and replaces the initial &lt;code&gt;Menu&lt;/code&gt; template variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2:&lt;/strong&gt; The returned content is inserted into the HTML structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3:&lt;/strong&gt; The remaining template variables, such as &lt;code&gt;PageTitle&lt;/code&gt; and &lt;code&gt;PageUrl&lt;/code&gt;, are replaced with their corresponding values.&lt;/p&gt;

&lt;p&gt;The final output contains the generated navigation links without requiring the loop to be written directly inside the HTML structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard Syntax Support
&lt;/h2&gt;

&lt;p&gt;Return Templates are also available in Standard Syntax.&lt;/p&gt;

&lt;p&gt;The equivalent HTML structure can be written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navigation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#Menu&lt;/span&gt;&lt;span class="err"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;#PageUrl#&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#PageTitle#&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/a&amp;gt;&lt;/span&gt;#&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding Return Template uses the Standard Syntax notation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#Menu&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="na"&gt;foreach&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;PageItem&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;model.PageItemList&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#Menu#&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
}
%&amp;gt;
#&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CodeBehind also handles transitions between standard server-side code blocks and returned template content, so developers do not need to manually manage every syntax boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Matters
&lt;/h2&gt;

&lt;p&gt;Return Templates provide a way to handle dynamic HTML without sacrificing the separation between presentation and server-side logic.&lt;/p&gt;

&lt;p&gt;This approach is particularly useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic navigation menus&lt;/li&gt;
&lt;li&gt;Repeated HTML structures&lt;/li&gt;
&lt;li&gt;Nested templates&lt;/li&gt;
&lt;li&gt;Complex page layouts&lt;/li&gt;
&lt;li&gt;Applications where multiple developers work on presentation and backend logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of moving HTML generation into Controllers or placing extensive control-flow statements inside Views, developers can keep each part in its appropriate place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Keeping presentation separate from application logic is not always straightforward, especially when pages contain dynamic and repetitive content.&lt;/p&gt;

&lt;p&gt;CodeBehind Return Templates provide another way to solve this problem. By separating the HTML structure from the server-side logic responsible for generating repeated content, developers can maintain cleaner Views and more manageable server-side code.&lt;/p&gt;

&lt;p&gt;The result is a more consistent Code-Behind architecture, particularly in applications with complex presentation requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;CodeBehind on GitHub:&lt;br&gt;
&lt;a href="https://github.com/elanatframework/CodeBehind" rel="noopener noreferrer"&gt;https://github.com/elanatframework/CodeBehind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeBehind in NuGet:&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/CodeBehind/" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/CodeBehind/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeBehind page:&lt;br&gt;
&lt;a href="https://elanat.net/codebehind" rel="noopener noreferrer"&gt;https://elanat.net/codebehind&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>backend</category>
    </item>
    <item>
      <title>Working with templates in View</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 05 Nov 2026 21:25:06 +0000</pubDate>
      <link>https://dev.to/elanatframework/working-with-templates-in-view-m2n</link>
      <guid>https://dev.to/elanatframework/working-with-templates-in-view-m2n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As web applications grow, maintaining repeated HTML structures across multiple pages can become a challenge. Page headers, product cards, information panels, and other common elements often share the same markup.&lt;/p&gt;

&lt;p&gt;Copying these structures into every view increases duplication and makes future changes more difficult.&lt;/p&gt;

&lt;p&gt;CodeBehind addresses this through its Template system. It allows developers to define reusable sections of a page and insert them into other parts of the view.&lt;/p&gt;

&lt;p&gt;Templates can be defined directly inside a page or stored in external files. Both Razor Syntax and Standard Syntax are supported.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Your First Template
&lt;/h2&gt;

&lt;p&gt;Consider an online store where several pages display product information using the same HTML structure.&lt;/p&gt;

&lt;p&gt;Instead of repeating the markup for every product, we can define a template named &lt;code&gt;ProductCard&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example using Razor Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@#ProductCard{
&amp;lt;div class="product-card"&amp;gt;
    &amp;lt;img src="@model.ProductImage" alt="@model.ProductName" /&amp;gt;
    &amp;lt;div class="product-info"&amp;gt;
        &amp;lt;h3&amp;gt;@model.ProductName&amp;lt;/h3&amp;gt;
        &amp;lt;p&amp;gt;@model.ProductDescription&amp;lt;/p&amp;gt;
        &amp;lt;span class="price"&amp;gt;@model.ProductPrice&amp;lt;/span&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template can then be referenced wherever its content is needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section class="products"&amp;gt;
    @#ProductCard
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When CodeBehind processes the page, the template reference is replaced with the content defined in &lt;code&gt;ProductCard&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This allows developers to maintain a single definition of a reusable HTML structure rather than duplicating it throughout the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Example in Standard Syntax
&lt;/h2&gt;

&lt;p&gt;CodeBehind provides the same capability through Standard Syntax.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ProductCard&lt;/code&gt; template can be defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#ProductCard&lt;/span&gt;
&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"product-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%=model.ProductImage%&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%=model.ProductName%&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"product-info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt;&lt;span class="na"&gt;model.ProductName&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt;&lt;span class="na"&gt;model.ProductDescription&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt;&lt;span class="na"&gt;model.ProductPrice&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
#&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To insert the template, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;#ProductCard#&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both examples demonstrate the same concept using their respective syntax conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizing Templates in External Files
&lt;/h2&gt;

&lt;p&gt;For larger applications, keeping all template definitions inside individual pages may not be the best approach.&lt;/p&gt;

&lt;p&gt;CodeBehind supports external template files through the &lt;code&gt;.astx&lt;/code&gt; extension. This makes it possible to organize reusable structures separately from the main page.&lt;/p&gt;

&lt;p&gt;For example, create the following file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/templates/product_card.astx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The file contains the template definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@#ProductCard{
&amp;lt;div class="product-card"&amp;gt;
    &amp;lt;img src="@model.ProductImage" alt="@model.ProductName" /&amp;gt;
    &amp;lt;h3&amp;gt;@model.ProductName&amp;lt;/h3&amp;gt;
    &amp;lt;p&amp;gt;@model.ProductDescription&amp;lt;/p&amp;gt;
    &amp;lt;span&amp;gt;@model.ProductPrice&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can reference this external template from a page using Razor Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page
@template "/templates/product_card.astx"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The equivalent Standard Syntax declaration is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%@&lt;/span&gt; &lt;span class="na"&gt;Page&lt;/span&gt; &lt;span class="na"&gt;Template=&lt;/span&gt;&lt;span class="s"&gt;"/templates/product_card.astx"&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.astx&lt;/code&gt; extension is optional when specifying the template path. Therefore, the following path is also valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/templates/product_card
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach allows multiple pages to use the same external template without maintaining separate copies of its HTML structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping Views Consistent Across an Application
&lt;/h2&gt;

&lt;p&gt;External templates are particularly useful when several sections of an application follow the same design conventions.&lt;/p&gt;

&lt;p&gt;For example, an online store might use shared templates for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product cards&lt;/li&gt;
&lt;li&gt;Category panels&lt;/li&gt;
&lt;li&gt;Customer information sections&lt;/li&gt;
&lt;li&gt;Order summaries&lt;/li&gt;
&lt;li&gt;Notification messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the design of a product card changes, developers only need to update its template instead of searching through multiple views.&lt;/p&gt;

&lt;p&gt;This also makes collaboration easier because developers can work on individual page structures while shared HTML components remain centrally organized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Template system in CodeBehind provides a practical way to organize and reuse HTML structures.&lt;/p&gt;

&lt;p&gt;By supporting inline definitions, external &lt;code&gt;.astx&lt;/code&gt; files, Razor Syntax, and Standard Syntax, it gives developers different options for managing their view structures.&lt;/p&gt;

&lt;p&gt;Rather than duplicating the same markup across an application, developers can define a template once and reuse it wherever necessary.&lt;/p&gt;

&lt;p&gt;Template feature is an important part of CodeBehind's approach to maintaining clean, organized, and reusable views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;CodeBehind on GitHub:&lt;br&gt;
&lt;a href="https://github.com/elanatframework/CodeBehind" rel="noopener noreferrer"&gt;https://github.com/elanatframework/CodeBehind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeBehind in NuGet:&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/CodeBehind/" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/CodeBehind/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeBehind page:&lt;br&gt;
&lt;a href="https://elanat.net/codebehind" rel="noopener noreferrer"&gt;https://elanat.net/codebehind&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>beginners</category>
      <category>backend</category>
    </item>
    <item>
      <title>WebForms Core 2.3 Progress Update: Component Begin, WebForms Core Begin!</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 29 Oct 2026 16:31:18 +0000</pubDate>
      <link>https://dev.to/elanatframework/webforms-core-23-progress-update-component-begin-webforms-core-begin-4nn8</link>
      <guid>https://dev.to/elanatframework/webforms-core-23-progress-update-component-begin-webforms-core-begin-4nn8</guid>
      <description>&lt;p&gt;&lt;strong&gt;WebForms Core 2.3 is getting close.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Around three to four weeks remain before the release, and a large part of the planned work has now been implemented. At this stage, development is mainly focused on completing the remaining pieces, integration, testing, and refining the new architecture.&lt;/p&gt;

&lt;p&gt;This is a progress update rather than another roadmap announcement. The features already explained in the &lt;a href="https://dev.to/elanatframework/webforms-core-23-will-be-released-in-november-2026-4n3c"&gt;previous 2.3 announcement&lt;/a&gt; are intentionally not repeated here. Instead, this post focuses on the new implementation work that has been completed or is now reaching completion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component System
&lt;/h2&gt;

&lt;p&gt;One of the most important developments in WebForms Core 2.3 is the implementation of the component execution boundary.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;BeginComponent&lt;/code&gt; method establishes a DOM scope for a component.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;BeginComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{component1}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that &lt;code&gt;BeginComponent&lt;/code&gt; does not need to know where the component exists in the DOM.&lt;/p&gt;

&lt;p&gt;When the event is executed on the client, WebForms Core starts from the element that triggered the event and walks upward through its parent elements until it reaches the component boundary specified by &lt;code&gt;BeginComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At that point, a &lt;code&gt;TransientDom&lt;/code&gt; is created for that component area.&lt;/p&gt;

&lt;p&gt;From then on, the Action Controls associated with that execution operate within the component's own DOM area.&lt;/p&gt;

&lt;p&gt;This creates an important separation between component instances.&lt;/p&gt;

&lt;p&gt;For example, if a page contains several instances of the same component, an event triggered inside one instance does not need to search or operate across the DOM of the other instances.&lt;/p&gt;

&lt;p&gt;The mechanism also covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buttons and their events&lt;/li&gt;
&lt;li&gt;Async execution&lt;/li&gt;
&lt;li&gt;Async conditions&lt;/li&gt;
&lt;li&gt;Intervals&lt;/li&gt;
&lt;li&gt;PreRunners&lt;/li&gt;
&lt;li&gt;Action Controls executed after the component boundary is established&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also special handling for &lt;code&gt;CommentBack&lt;/code&gt;. When &lt;code&gt;CommentBack&lt;/code&gt; is involved, the component's &lt;code&gt;TransientDom&lt;/code&gt; is used so that the &lt;code&gt;CommentBack&lt;/code&gt; operation is performed only once for that component scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  DoComponent
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;DoComponent&lt;/code&gt; takes this one step further.&lt;/p&gt;

&lt;p&gt;Instead of requiring the developer to manually establish every component boundary, &lt;code&gt;DoComponent&lt;/code&gt; automatically generates the required &lt;code&gt;BeginComponent&lt;/code&gt; instructions.&lt;/p&gt;

&lt;p&gt;It also creates a component boundary for each generated index where necessary.&lt;/p&gt;

&lt;p&gt;This means the component mechanism can be used both explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;BeginComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{component1}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and through higher-level component generation with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;DoComponent&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a scoped execution model without requiring server-side UI rendering.&lt;/p&gt;

&lt;p&gt;The component system is therefore no longer just a planned concept in WebForms Core 2.3. Its execution mechanism is now being implemented directly inside the WebForms Core command model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component Begin, WebForms Core Begin.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  RenderList
&lt;/h2&gt;

&lt;p&gt;A new declarative method called &lt;code&gt;RenderList&lt;/code&gt; has also been added.&lt;/p&gt;

&lt;p&gt;Previously, rendering a collection could require combining several operations such as &lt;code&gt;foreach&lt;/code&gt;, &lt;code&gt;AddText&lt;/code&gt;, template binding, and other related instructions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RenderList&lt;/code&gt; provides a higher-level abstraction that combines these operations.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RenderList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;inputPlace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"series-container"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/template.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SeriesSite"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{{value}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"[0]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method is designed to simplify repeated template rendering while keeping the implementation declarative.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TransientDom&lt;/code&gt; is also handled automatically.&lt;/p&gt;

&lt;p&gt;The goal is not to introduce another rendering engine, but to provide a simpler way to express a common WebForms Core operation.&lt;/p&gt;




&lt;h2&gt;
  
  
  GetFormJSON
&lt;/h2&gt;

&lt;p&gt;A new &lt;code&gt;GetFormJSON&lt;/code&gt; method has been added to the &lt;code&gt;Fetch&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;It provides a direct way to retrieve the values of a form and represent them as JSON.&lt;/p&gt;

&lt;p&gt;This gives WebForms Core a simple mechanism for moving form data into JavaScript-side processing without requiring developers to manually construct the JSON structure.&lt;/p&gt;

&lt;p&gt;It also establishes a foundation for more advanced data handling features being developed for the new Variable system.&lt;/p&gt;




&lt;h2&gt;
  
  
  A New Variable System
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm5qp6d2ov1aso4k3xtkm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm5qp6d2ov1aso4k3xtkm.jpg" alt="WebForms Core 2.3 Comming Soon!" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another major area of development is the new Variable mechanism.&lt;/p&gt;

&lt;p&gt;Instead of creating a simple mirrored-value structure, WebForms Core 2.3 is moving toward a more advanced variable system.&lt;/p&gt;

&lt;p&gt;The idea is to allow values such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{value}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to become actual variables within a defined scope.&lt;/p&gt;

&lt;p&gt;The variable information can be represented as a name/value list in an INI-like structure stored through HTML comments within the relevant tag scope.&lt;/p&gt;

&lt;p&gt;When a value changes, the corresponding bound values can be updated as well.&lt;/p&gt;

&lt;p&gt;If the variable structure does not already exist, the system can create it automatically.&lt;/p&gt;

&lt;p&gt;The Variable system is being separated from form data management.&lt;/p&gt;

&lt;p&gt;The two concepts are therefore treated independently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[variable]
[form-data]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction is important because a variable is not necessarily form data, and form data does not necessarily represent the state of a component or element.&lt;/p&gt;

&lt;p&gt;The retrieval side of this mechanism is being organized around &lt;code&gt;FetchVariable&lt;/code&gt;, while operations such as &lt;code&gt;SetVariable&lt;/code&gt; and &lt;code&gt;BindVariable&lt;/code&gt; provide ways to update and bind values.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SetVariable&lt;/code&gt; is being designed to accept arbitrary data, convert it into JSON when appropriate, and then update the Variable structure.&lt;/p&gt;

&lt;p&gt;The Variable system is also being extended with operations for manipulating values, including replacement, arithmetic operations, text extraction, appending, and prepending.&lt;/p&gt;

&lt;p&gt;This is one of the larger pieces of the 2.3 data-management work and is still being refined.&lt;/p&gt;




&lt;h2&gt;
  
  
  Page-Level Race Condition Protection
&lt;/h2&gt;

&lt;p&gt;Another important part of the current development is protection against stale operations.&lt;/p&gt;

&lt;p&gt;Consider a user who quickly performs two actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change the language to English.&lt;/li&gt;
&lt;li&gt;Immediately change the language back to Persian.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the first request takes longer to return, its response could arrive after the second request.&lt;/p&gt;

&lt;p&gt;Without protection, an older response could modify a page that has already moved to a newer state.&lt;/p&gt;

&lt;p&gt;WebForms Core 2.3 is being developed to treat these operations as ordered requests.&lt;/p&gt;

&lt;p&gt;The request execution model will track requests with increasing identifiers. In addition to the existing Action Control execution queue, request execution itself is being tracked.&lt;/p&gt;

&lt;p&gt;When the page changes, the system can determine whether a pending request or Action Control belongs to an older page state.&lt;/p&gt;

&lt;p&gt;If it does, it becomes obsolete.&lt;/p&gt;

&lt;p&gt;The old operation must then be ignored even if its response has already arrived.&lt;/p&gt;

&lt;p&gt;This provides protection against several related problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Race Conditions&lt;/strong&gt; — multiple operations competing to update the page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale Responses&lt;/strong&gt; — a response belonging to an older page state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cancellation&lt;/strong&gt; — preventing obsolete Action Controls from executing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-order responses&lt;/strong&gt; — ensuring that an older response cannot overwrite a newer state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important point is that this is not limited to server responses.&lt;/p&gt;

&lt;p&gt;The same protection must apply to Action Controls that are already waiting in the client execution flow.&lt;/p&gt;

&lt;p&gt;The goal is a simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Once the page has moved to a newer state, operations belonging to the previous state must no longer be allowed to modify the current page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially important for fast user interactions and applications where multiple server requests can be generated within a very short period.&lt;/p&gt;




&lt;h2&gt;
  
  
  Replacing the &lt;code&gt;*&lt;/code&gt; Magic Character in DeleteAll
&lt;/h2&gt;

&lt;p&gt;A protocol-level ambiguity in &lt;code&gt;DeleteAll&lt;/code&gt; has also been addressed.&lt;/p&gt;

&lt;p&gt;Previously, &lt;code&gt;*&lt;/code&gt; was used as a special value to represent "delete everything".&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"do"&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dk"&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that &lt;code&gt;*&lt;/code&gt; can also be a legitimate value.&lt;/p&gt;

&lt;p&gt;If an actual &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; or checkbox value is exactly &lt;code&gt;*&lt;/code&gt;, the protocol cannot distinguish between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Delete the item whose value is *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Delete all items
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WebForms Core 2.3 replaces this magic-character approach with a dedicated flag structure.&lt;/p&gt;

&lt;p&gt;This removes the ambiguity and allows &lt;code&gt;*&lt;/code&gt; to be treated as a normal value when necessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  SafeValue Now Handles HTML Encoding
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;SafeValue&lt;/code&gt; has also been improved.&lt;/p&gt;

&lt;p&gt;It now performs HTML encoding in addition to its existing processing, providing a centralized mechanism for safely handling values that are inserted into HTML-related output.&lt;/p&gt;

&lt;p&gt;The goal is to avoid requiring developers to remember separate encoding operations in different parts of the framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  UpdateLineByIndex Fix
&lt;/h2&gt;

&lt;p&gt;An edge case involving empty values in &lt;code&gt;UpdateLineByIndex&lt;/code&gt; has been fixed.&lt;/p&gt;

&lt;p&gt;Previously, an empty value could result in an additional &lt;code&gt;=&lt;/code&gt; being generated for an Action Control that did not actually contain an assigned value.&lt;/p&gt;

&lt;p&gt;This could produce malformed or ambiguous command output.&lt;/p&gt;

&lt;p&gt;The new behavior correctly preserves empty values without introducing an unnecessary assignment character.&lt;/p&gt;




&lt;h2&gt;
  
  
  WebFormsJS Improvements
&lt;/h2&gt;

&lt;p&gt;Several internal improvements have also been made to WebFormsJS.&lt;/p&gt;

&lt;p&gt;The options section has been converted to an Object Initializer structure.&lt;/p&gt;

&lt;p&gt;This reduces the amount of code and makes the configuration structure easier to read and maintain.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WebFormsOptions&lt;/code&gt; has also been renamed to &lt;code&gt;WFO&lt;/code&gt;, reducing the size of the library and simplifying the API.&lt;/p&gt;

&lt;p&gt;Two non-ASCII characters have been removed from the WebFormsJS source as part of the ongoing effort to keep the client-side library compact and predictable.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; Becomes the Default Location
&lt;/h2&gt;

&lt;p&gt;One of the more practical changes in WebFormsJS 2.3 is the default location used by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ResponseLocation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StateBodyLocation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default has been changed from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is also an automatic fallback.&lt;/p&gt;

&lt;p&gt;If a &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element does not exist, WebFormsJS uses &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This change removes one of the configuration steps that previously had to be recommended to developers.&lt;/p&gt;

&lt;p&gt;As a result, the WebFormsJS 2.3 package can now be consumed directly from a CDN without requiring developers to download and host the library themselves.&lt;/p&gt;

&lt;p&gt;The package size is approximately &lt;strong&gt;45 KB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For applications that do not need to customize these locations, the result is a simpler setup with less configuration and a very small client-side payload.&lt;/p&gt;




&lt;h2&gt;
  
  
  Modal
&lt;/h2&gt;

&lt;p&gt;A dedicated Modal API has also been introduced.&lt;/p&gt;

&lt;p&gt;The existing concept is essentially a container or &lt;code&gt;Box&lt;/code&gt;, but &lt;strong&gt;Modal&lt;/strong&gt; is the terminology commonly used on the web for this type of UI.&lt;/p&gt;

&lt;p&gt;A modal can be opened with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ShowModal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and removed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CloseModal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides a clearer high-level API for a very common UI pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Left?
&lt;/h2&gt;

&lt;p&gt;With the release approximately three to four weeks away, the project has moved from architectural design into final implementation and refinement.&lt;/p&gt;

&lt;p&gt;The major new foundations are now in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Component-scoped execution through &lt;code&gt;BeginComponent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Automatic component boundaries through &lt;code&gt;DoComponent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Declarative collection rendering through &lt;code&gt;RenderList&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Form-to-JSON conversion through &lt;code&gt;GetFormJSON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The new Variable system&lt;/li&gt;
&lt;li&gt;Improved value handling through &lt;code&gt;SafeValue&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Protocol improvements for &lt;code&gt;DeleteAll&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;WebFormsJS size and configuration improvements&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;-based default locations with automatic &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; fallback&lt;/li&gt;
&lt;li&gt;Page-level protection against stale requests and Action Controls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The remaining work is primarily focused on completing the Variable operations, finalizing request lifecycle handling, integration testing, edge cases, and polishing the APIs before release.&lt;/p&gt;

&lt;p&gt;WebForms Core 2.3 is becoming much more than an incremental update.&lt;/p&gt;

&lt;p&gt;The component boundary, scoped execution, data binding, variable management, request lifecycle, and client-side execution model are increasingly becoming parts of one coherent system.&lt;/p&gt;

&lt;p&gt;And the most important part is that this is still the same WebForms Core philosophy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The server provides the commands. WebFormsJS executes them on the client.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But with 2.3, those commands can now operate with much stronger boundaries, better lifecycle control, and a more structured component model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebForms Core 2.3 is getting close.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;Official WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;Official WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;WebForms Core Demo Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>news</category>
      <category>architecture</category>
      <category>component</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>WFC in R Programming Language</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 22 Oct 2026 13:42:29 +0000</pubDate>
      <link>https://dev.to/elanatframework/wfc-in-r-programming-language-fgp</link>
      <guid>https://dev.to/elanatframework/wfc-in-r-programming-language-fgp</guid>
      <description>&lt;p&gt;&lt;strong&gt;WebForms Core (WFC)&lt;/strong&gt; is now available for R, bringing server-side UI manipulation and server-orchestrated browser interaction to the R programming language.&lt;/p&gt;

&lt;p&gt;WebForms Core is a Server-Driven UI technology built around a stateless server that does not dynamically render the UI. Its output is standard HTML without framework-specific attributes or tags. WebForms Core uses a compact INI-based format for communication between the server and browser and can be implemented in different web programming languages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;webformscore&lt;/code&gt; package provides the R implementation of the WebForms class, allowing R applications to generate WebForms Core commands that are executed in the browser by WebFormsJS.&lt;/p&gt;

&lt;p&gt;This makes it possible to build interactive web interfaces in R without creating a separate JavaScript application or manually writing JavaScript for UI behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebForms Core in R
&lt;/h2&gt;

&lt;p&gt;WebForms Core uses a &lt;strong&gt;Commander–Executor&lt;/strong&gt; architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    R Application
          │
          ▼
    WebForms Class
          │
          │ WebForms Core Commands
          │
          ▼
WebFormsJS Browser Runtime
          │
          ▼
      HTML DOM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an R application, the &lt;code&gt;WebForms&lt;/code&gt; class — provided by the &lt;code&gt;webformscore&lt;/code&gt; package — acts as the &lt;strong&gt;Commander&lt;/strong&gt;. It constructs a sequence of WebForms Core commands that describe UI operations and interaction logic.&lt;/p&gt;

&lt;p&gt;WebFormsJS runs in the browser as the &lt;strong&gt;Executor&lt;/strong&gt;. It parses those commands and performs the corresponding operations on the HTML DOM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk50say8krzfr7sem2dbe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk50say8krzfr7sem2dbe.jpg" alt="WebForms Core in R" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The R application therefore does not need to directly manipulate the browser DOM with JavaScript. R is responsible for constructing the command sequence, while the browser runtime is responsible for executing it.&lt;/p&gt;

&lt;p&gt;This also shows that WebForms Core is not tied to a particular server language. The same architectural concept can be implemented across different programming languages through their corresponding WebForms classes. In R, this allows R to participate directly in server-orchestrated web interfaces without requiring a separate front-end framework or a separate JavaScript application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;webformscore&lt;/code&gt; package can be installed from CRAN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;install.packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"webformscore"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then load it in an R application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webformscore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A web server such as &lt;code&gt;httpuv&lt;/code&gt; can be used to expose the R application over HTTP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpuv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webformscore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebForms class is provided by the &lt;code&gt;webformscore&lt;/code&gt; package, while WebFormsJS runs on the client side.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Digital Clock with WFC
&lt;/h2&gt;

&lt;p&gt;The following example creates a digital clock using R, &lt;code&gt;httpuv&lt;/code&gt;, WebForms Core, and WebFormsJS.&lt;/p&gt;

&lt;p&gt;The clock updates every second. The time is obtained through WebForms Core date values, formatted on the server-command side, and assigned to the HTML element.&lt;/p&gt;

&lt;p&gt;No custom JavaScript is written for the clock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpuv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webformscore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;html_form&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s1"&gt;'
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;WebForms Core Technology in R - Digital Clock Example&amp;lt;/title&amp;gt;
    &amp;lt;script type="module" src="/script/web-forms.js"&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;style&amp;gt;
        body {
            margin: 0;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: #111;
            color: #fff;
            font-family: Arial, sans-serif;
        }

        h1 {
            margin-bottom: 30px;
            font-size: 28px;
            font-weight: normal;
        }

        #Clock {
            padding: 30px 45px;
            border: 2px solid #333;
            border-radius: 12px;
            background: #000;
            color: #00ff66;
            font-family: "Courier New", monospace;
            font-size: 64px;
            font-weight: bold;
            letter-spacing: 6px;
            box-shadow:
                0 0 15px rgba(0, 255, 102, 0.25),
                inset 0 0 20px rgba(0, 255, 102, 0.08);
            text-shadow:
                0 0 5px #00ff66,
                0 0 15px rgba(0, 255, 102, 0.7);
        }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;WebForms Core Technology in R&amp;lt;/h1&amp;gt;

    &amp;lt;div id="Clock"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;REQUEST_METHOD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;PATH_INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/script/web-forms.js"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;200L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/javascript; charset=utf-8"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;readLines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"script/web-forms.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;warn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;collapse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\n"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;REQUEST_METHOD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;PATH_INFO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WebForms&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;add_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Hour}}:{{Minute}}:{{Second}}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;replace_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Hour}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_hours&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;replace_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Minute}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_minutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;replace_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Second}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;set_format_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(^|:)(\\d)(?=:|$)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$$10$2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;set_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Clock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;go_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31536000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

            &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;200L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/html; charset=utf-8"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paste0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;html_form&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;export_to_html_comment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;404L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text/plain"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Not Found"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;startServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Screenshot of Digital Clock&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fftxfnr7mvl2gr7am8aro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fftxfnr7mvl2gr7am8aro.png" alt="WebForms Core in R - Digital Clock Example" width="548" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Note on the &lt;code&gt;script/web-forms.js&lt;/code&gt; Path
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;script/web-forms.js&lt;/code&gt; path is relative to the R session's &lt;strong&gt;working directory&lt;/strong&gt;. Make sure the file is available under this path when the server starts. You can check the working directory with &lt;code&gt;getwd()&lt;/code&gt; or change it with &lt;code&gt;setwd()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The clock starts by creating a &lt;code&gt;WebForms&lt;/code&gt; instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WebForms&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A temporary saved value is then created for the clock format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;add_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Hour}}:{{Minute}}:{{Second}}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The placeholders are replaced using WebForms Core date values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_hours&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_minutes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_seconds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;replace_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{Hour}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;date_hours&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;set_format_save_value&lt;/code&gt; function applies (regex-based) formatting to the stored value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;set_format_save_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(^|:)(\\d)(?=:|$)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$$10$2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pattern &lt;code&gt;(^|:)(\\d)(?=:|$)&lt;/code&gt; matches a single digit that appears either at the beginning of the string or immediately after a &lt;code&gt;:&lt;/code&gt;, and is followed by either a &lt;code&gt;:&lt;/code&gt; or the end of the string. Group 1 (&lt;code&gt;$1&lt;/code&gt;) captures the start or the &lt;code&gt;:&lt;/code&gt;, and group 2 (&lt;code&gt;$2&lt;/code&gt;) captures the digit itself.&lt;/p&gt;

&lt;p&gt;In the replacement string &lt;code&gt;"$$10$2"&lt;/code&gt;, the double dollar sign &lt;code&gt;$$&lt;/code&gt; escapes the dollar sign so it is not interpreted as direct access to a JavaScript object, such as &lt;code&gt;$document&lt;/code&gt;. After this escaping, the replacement effectively becomes &lt;code&gt;$1&lt;/code&gt; + &lt;code&gt;0&lt;/code&gt; + &lt;code&gt;$2&lt;/code&gt;: it keeps the captured delimiter, inserts a literal &lt;code&gt;0&lt;/code&gt;, and then keeps the captured digit. This adds the leading zero required for a conventional digital clock.&lt;/p&gt;

&lt;p&gt;For example, when the hour is &lt;code&gt;7&lt;/code&gt;, the result becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;07
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while an hour such as &lt;code&gt;17&lt;/code&gt; remains unchanged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting value is assigned to the &lt;code&gt;Clock&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;set_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Clock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"clock-format"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command sequence then waits for one second:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and continues the execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;go_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;31536000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WebFormsJS executes these commands in the browser, causing the displayed time to update continuously.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Manual JavaScript
&lt;/h2&gt;

&lt;p&gt;One of the important aspects of this example is what is &lt;strong&gt;not&lt;/strong&gt; present.&lt;/p&gt;

&lt;p&gt;There is no code such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no DOM manipulation such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no custom JavaScript clock implementation.&lt;/p&gt;

&lt;p&gt;The only JavaScript loaded by the page is the WebFormsJS runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/script/web-forms.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The behavior of the clock is described through WebForms Core commands generated from R.&lt;/p&gt;

&lt;p&gt;This demonstrates the distinction between the &lt;strong&gt;application language&lt;/strong&gt; and the &lt;strong&gt;browser runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;R describes the behavior.&lt;/p&gt;

&lt;p&gt;WebFormsJS executes the behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing WebFormsJS
&lt;/h3&gt;

&lt;p&gt;The latest WebFormsJS Executor is available through npm or as a downloadable JavaScript file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation via Package&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;npm package: &lt;a href="https://www.npmjs.com/package/webformsjs" rel="noopener noreferrer"&gt;webformsjs&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;webformsjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Download / Copy the File&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;WebFormsJS on Elanat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Is Interesting for R
&lt;/h2&gt;

&lt;p&gt;R is traditionally associated with statistical computing, data analysis, scientific computing, and research applications.&lt;/p&gt;

&lt;p&gt;With WebForms Core, R can also be used to construct interactive browser interfaces using the same server-orchestrated UI model.&lt;/p&gt;

&lt;p&gt;This can be useful for applications such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data analysis interfaces&lt;/li&gt;
&lt;li&gt;Scientific dashboards&lt;/li&gt;
&lt;li&gt;Research tools&lt;/li&gt;
&lt;li&gt;Interactive reports&lt;/li&gt;
&lt;li&gt;Internal applications&lt;/li&gt;
&lt;li&gt;Data-driven forms&lt;/li&gt;
&lt;li&gt;Administrative interfaces&lt;/li&gt;
&lt;li&gt;Real-time UI experiments&lt;/li&gt;
&lt;li&gt;Browser-based R applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important point is that the browser does not need to be treated as a completely separate application.&lt;/p&gt;

&lt;p&gt;The server can orchestrate the interface through WebForms Core commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The digital clock is a small example, but it demonstrates an important capability: &lt;strong&gt;R can be used to construct browser UI behavior through WebForms Core without manually programming the browser in JavaScript.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application uses R and the &lt;code&gt;webformscore&lt;/code&gt; package to create the commands, while WebFormsJS provides the browser-side runtime that executes them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;R → WebForms → Commands → WebFormsJS → HTML DOM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens the door to using R not only as a data and computation language, but also as a server-side Commander for interactive web interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;In Elanat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;in GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;WebForms Core Demo Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>r</category>
      <category>httpuv</category>
      <category>backend</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>WebForms Core 2.3 Will Be Released in November 2026</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Sat, 17 Oct 2026 14:14:00 +0000</pubDate>
      <link>https://dev.to/elanatframework/webforms-core-23-will-be-released-in-november-2026-4n3c</link>
      <guid>https://dev.to/elanatframework/webforms-core-23-will-be-released-in-november-2026-4n3c</guid>
      <description>&lt;p&gt;&lt;strong&gt;WebForms Core 2.3&lt;/strong&gt; is currently under development, introducing improvements to component-based development, resource lifecycle management, request handling, state management, and client-side execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component System &amp;amp; Scope
&lt;/h2&gt;

&lt;p&gt;The new component system is one of the major architectural additions planned for WebForms Core 2.3. It is being developed to bring the benefits of component-based development to WebForms Core's distinctive architecture, which uses server-driven commands, client-side execution, and a stateless server without server-side UI rendering.&lt;/p&gt;

&lt;p&gt;The component system is designed to provide the following capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reusability&lt;/strong&gt; — Create a component once and reuse it in multiple places across an application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component Isolation&lt;/strong&gt; — Keep each component instance's DOM operations and event handling within its own scope, preventing multiple instances of the same component from interfering with one another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt; — Organize application functionality into independent components, making code easier to maintain and extend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composability&lt;/strong&gt; — Combine individual components to build more complex user interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent Component State&lt;/strong&gt; — Allow each component instance to maintain its own state without unintentionally affecting other instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scoped Event Handling&lt;/strong&gt; — Execute component events and their associated Action Controls within the appropriate component scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parameter-Based Communication&lt;/strong&gt; — Support passing data and configuration between components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-Based Communication&lt;/strong&gt; — Allow components to communicate through events and respond to interactions with other components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt; — Make individual components easier to test by keeping their behavior and responsibilities organized within defined boundaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to make components reusable, independent, and easier to manage while preserving the existing WebForms Core execution model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: A Counter Component in Blazor Server
&lt;/h3&gt;

&lt;p&gt;The following example demonstrates the concept of independent component instances in Blazor Server. Keep it in mind until WebForms Core 2.3 is released to better understand the component-based approach being developed for WebForms Core.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File: &lt;code&gt;Components/Counter.razor&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h3&amp;gt;Counter: @count&amp;lt;/h3&amp;gt;

&amp;lt;button class="btn btn-primary" @onclick="Increment"&amp;gt;
    Increment
&amp;lt;/button&amp;gt;

@code {
    private int count = 0;

    private void Increment()
    {
        count++;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component contains markup, state, and event-handling logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File: &lt;code&gt;Components/Pages/Home.razor&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page "/"

&amp;lt;h1&amp;gt;Home Page&amp;lt;/h1&amp;gt;

&amp;lt;Counter /&amp;gt;
&amp;lt;Counter /&amp;gt;
&amp;lt;Counter /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By placing &lt;code&gt;&amp;lt;Counter /&amp;gt;&lt;/code&gt; three times, Blazor creates three independent component instances. Each instance maintains its own &lt;code&gt;count&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;This example illustrates the concept of component reuse and instance isolation. WebForms Core 2.3 is being developed to bring comparable component-oriented benefits to a different architecture, where the server sends commands and WebFormsJS executes them on the client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu84beri3or3uw5n6lvaw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu84beri3or3uw5n6lvaw.jpg" alt="Support for Component-Based Development in WebForms Core" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  EnableAutoCleanup
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;EnableAutoCleanup&lt;/code&gt; is a new method being developed to simplify resource lifecycle management.&lt;/p&gt;

&lt;p&gt;When enabled, resources associated with the current page can be registered for cleanup and released when the page changes. These resources may include Event Listeners, Timers, Custom Events, Snapshots, Cache entries, Save data, IndexedDB data, and other resources that are no longer needed.&lt;/p&gt;

&lt;p&gt;The purpose is to reduce manual cleanup work and help prevent obsolete resources and event handlers from remaining active after navigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request &amp;amp; Action Control Lifecycle Management
&lt;/h2&gt;

&lt;p&gt;Request handling and Action Control execution are being improved to prevent outdated operations from affecting the current page.&lt;/p&gt;

&lt;p&gt;When users trigger multiple operations in quick succession, an earlier request may return after a newer request has already changed the page state. WebForms Core 2.3 is being developed to identify such obsolete requests and prevent their responses or associated Action Controls from executing when they no longer belong to the current page state.&lt;/p&gt;

&lt;p&gt;This includes improved handling of request ordering, stale responses, and Action Controls associated with previous page states.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendered Value Mirroring
&lt;/h2&gt;

&lt;p&gt;A new structure for mirroring rendered values into Cache and Save is being developed.&lt;/p&gt;

&lt;p&gt;The mechanism is designed to compare a stored snapshot with the current &lt;code&gt;outerHTML&lt;/code&gt;, identify relevant changes, and represent changed values in a suitable key-value structure. This can provide a consistent basis for retrieving and updating preserved data.&lt;/p&gt;

&lt;h2&gt;
  
  
  RunWebForms
&lt;/h2&gt;

&lt;p&gt;A new &lt;code&gt;RunWebForms&lt;/code&gt; method has been added to execute Action Controls on the client side programmatically.&lt;/p&gt;

&lt;p&gt;This provides an additional way to run WebForms Core instructions without relying exclusively on their automatic execution through the usual processing flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  SetResponse
&lt;/h2&gt;

&lt;p&gt;A new &lt;code&gt;SetResponse&lt;/code&gt; method has been added to programmatically add HTML, Action Controls, and other data to a response.&lt;/p&gt;

&lt;p&gt;It also supports scenarios in which HTML comments contain WebForms Core instructions that need to be processed on the client side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hash URL State Management
&lt;/h2&gt;

&lt;p&gt;State management for URLs containing hashes has been improved to provide more consistent behavior when navigating between hash-based locations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transient DOM Improvements
&lt;/h2&gt;

&lt;p&gt;An issue that could cause an execution loop when Transient DOM was used on elements containing Comment Action Controls has been resolved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loader Improvements
&lt;/h2&gt;

&lt;p&gt;Loader behavior has been improved with new configuration options for controlling Loader animations, including situations in which data arrives quickly.&lt;/p&gt;

&lt;p&gt;The default Loader animation behavior has also been adjusted for &lt;code&gt;CommentBack&lt;/code&gt;, with additional configuration options for &lt;code&gt;WasmBack&lt;/code&gt; and &lt;code&gt;FrontBack&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SPALink Improvements
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;SPALink&lt;/code&gt; behavior has been improved to allow its settings to be restored to their initial state when required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Form Behavior
&lt;/h2&gt;

&lt;p&gt;The behavior of &lt;code&gt;button&lt;/code&gt; and &lt;code&gt;input&lt;/code&gt; elements with &lt;code&gt;type="submit"&lt;/code&gt; has been aligned more closely with the browser's default form behavior.&lt;/p&gt;

&lt;p&gt;An issue that could cause an additional &lt;code&gt;null&lt;/code&gt; value to be submitted when an element did not have a &lt;code&gt;name&lt;/code&gt; attribute has also been resolved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall Direction
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.3 continues to build on the &lt;strong&gt;Commander-Executor architecture&lt;/strong&gt;, in which the server provides commands and WebFormsJS executes them on the client.&lt;/p&gt;

&lt;p&gt;The planned component system aims to combine reusable UI structures, scoped DOM operations, isolated component instances, and component communication with this architecture. Alongside &lt;code&gt;EnableAutoCleanup&lt;/code&gt;, improved request lifecycle management, and state preservation, these developments are intended to make WebForms Core applications easier to organize and maintain without requiring server-side UI rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;Official WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;Official WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;WebForms Core Demo Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>news</category>
      <category>opensource</category>
      <category>blazor</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>CodeBehind Is About 19% Faster Than ASP.NET MVC in the Latest Benchmark</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Fri, 16 Oct 2026 20:59:25 +0000</pubDate>
      <link>https://dev.to/elanatframework/codebehind-is-about-19-faster-than-aspnet-mvc-in-the-latest-benchmark-2ec1</link>
      <guid>https://dev.to/elanatframework/codebehind-is-about-19-faster-than-aspnet-mvc-in-the-latest-benchmark-2ec1</guid>
      <description>&lt;p&gt;&lt;strong&gt;CodeBehind 4.8&lt;/strong&gt;, the server-side web framework developed by &lt;strong&gt;Elanat&lt;/strong&gt;, has reached a significant performance milestone in the latest Web Frameworks Benchmark.&lt;/p&gt;

&lt;p&gt;According to the benchmark results published on October 6, 2026, CodeBehind 4.8 processes substantially more requests per second than ASP.NET MVC 10 across all three tested request sizes.&lt;/p&gt;

&lt;p&gt;The benchmark comparison is available on the &lt;a href="https://web-frameworks-benchmark.netlify.app/result?l=csharp" rel="noopener noreferrer"&gt;Web Frameworks Benchmark results page for C#&lt;/a&gt;, where you can review CodeBehind 4.8 alongside ASP.NET MVC and other C# web frameworks.&lt;/p&gt;

&lt;p&gt;On average, &lt;strong&gt;CodeBehind is about 19% faster than ASP.NET MVC&lt;/strong&gt; in these results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmark Results
&lt;/h2&gt;

&lt;p&gt;The benchmark reports the following results for C# frameworks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Requests/s (64)&lt;/th&gt;
&lt;th&gt;Requests/s (256)&lt;/th&gt;
&lt;th&gt;Requests/s (512)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ASP.NET Minimal API&lt;/td&gt;
&lt;td&gt;166,518&lt;/td&gt;
&lt;td&gt;147,805&lt;/td&gt;
&lt;td&gt;143,096&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carter&lt;/td&gt;
&lt;td&gt;166,262&lt;/td&gt;
&lt;td&gt;146,862&lt;/td&gt;
&lt;td&gt;141,774&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CodeBehind 4.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;139,431&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;127,252&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;126,435&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FastEndpoints&lt;/td&gt;
&lt;td&gt;135,409&lt;/td&gt;
&lt;td&gt;125,525&lt;/td&gt;
&lt;td&gt;123,542&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ASP.NET MVC 10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;114,011&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;108,498&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;107,883&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Effinitive Framework&lt;/td&gt;
&lt;td&gt;107,160&lt;/td&gt;
&lt;td&gt;103,343&lt;/td&gt;
&lt;td&gt;103,860&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GenHTTP&lt;/td&gt;
&lt;td&gt;101,527&lt;/td&gt;
&lt;td&gt;95,798&lt;/td&gt;
&lt;td&gt;98,406&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simplify.Web&lt;/td&gt;
&lt;td&gt;56,881&lt;/td&gt;
&lt;td&gt;57,221&lt;/td&gt;
&lt;td&gt;56,785&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The direct comparison between CodeBehind and ASP.NET MVC is particularly interesting:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request Size&lt;/th&gt;
&lt;th&gt;CodeBehind 4.8&lt;/th&gt;
&lt;th&gt;ASP.NET MVC 10&lt;/th&gt;
&lt;th&gt;CodeBehind Advantage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;139,431&lt;/td&gt;
&lt;td&gt;114,011&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;22.3%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;127,252&lt;/td&gt;
&lt;td&gt;108,498&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;17.3%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;126,435&lt;/td&gt;
&lt;td&gt;107,883&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;17.2%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Taking the three comparisons together, CodeBehind's average advantage is approximately &lt;strong&gt;19%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9dzuj2w7l8jd9oye410c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9dzuj2w7l8jd9oye410c.png" alt="ASP.NET Frameworks" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This comparison is particularly significant because &lt;strong&gt;CodeBehind is a versatile, feature-rich web framework&lt;/strong&gt; capable of supporting different development models and architectural approaches. It can provide MVC, MVC First-View, WebForms Core, and other approaches to server-side web development, making it comparable in scope to Microsoft's three major .NET web frameworks: &lt;strong&gt;ASP.NET Core MVC&lt;/strong&gt;, &lt;strong&gt;Razor Pages&lt;/strong&gt;, and &lt;strong&gt;Blazor&lt;/strong&gt;. Through its integration with WebForms Core, CodeBehind also supports server-orchestrated UI manipulation using WebForms commands and WebFormsJS, with features such as Render, Snapshot, Rollback, and TransientDom. Achieving approximately 19% higher average throughput than ASP.NET MVC in the reported benchmark is particularly noteworthy given the versatility and range of capabilities CodeBehind offers.&lt;/p&gt;

&lt;h3&gt;
  
  
  An Important Detail About the CodeBehind Execution Model
&lt;/h3&gt;

&lt;p&gt;CodeBehind uses a code-generation and compilation process to prepare its View and Controller execution paths. During initial startup, or after relevant structural changes, it generates a C# source file containing a &lt;code&gt;switch&lt;/code&gt; statement for route handling and dedicated asynchronous methods for individual Views and Controllers. It then compiles this generated source code and loads the resulting assembly.&lt;/p&gt;

&lt;p&gt;For example, a route such as &lt;code&gt;/series/Default.aspx&lt;/code&gt; can be mapped to a dedicated method such as &lt;code&gt;_series_Default_aspx_SeriesSiteController_PageLoad1&lt;/code&gt;. Once compilation is complete, request handling uses the generated, compiled execution paths instead of regenerating and recompiling this code for every request. This process is triggered again when required by application restarts, redeployment, or structural changes to Views and Controllers. With precompilation, the generation and compilation cost can also be moved to the build or deployment stage.&lt;/p&gt;

&lt;p&gt;This distinction is important when interpreting performance benchmarks: &lt;strong&gt;the initial code-generation and compilation cost is separate from steady-state request throughput&lt;/strong&gt;. Whether it affects a particular benchmark depends on how that benchmark measures application startup and request processing. The reported results establish CodeBehind's approximately 19% average throughput advantage over ASP.NET MVC in the three tested scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Performance Did Not Come From a Single Change
&lt;/h2&gt;

&lt;p&gt;The performance gap is the result of continuous engineering work by Elanat.&lt;/p&gt;

&lt;p&gt;CodeBehind has been developed with a strong focus on reducing unnecessary processing in the server-side request pipeline while maintaining a structured programming model for server-side web applications.&lt;/p&gt;

&lt;p&gt;Recent releases have introduced several important architectural and implementation improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing Unnecessary Processing
&lt;/h3&gt;

&lt;p&gt;One example is the removal of the &lt;code&gt;Control&lt;/code&gt; method in CodeBehind 4.8.&lt;/p&gt;

&lt;p&gt;Although the overhead of this method was relatively small, it introduced additional processing during requests. Removing it eliminates that unnecessary path from the framework.&lt;/p&gt;

&lt;p&gt;This is an important principle in performance-oriented framework development:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Small amounts of unnecessary work become significant when they are repeated across a large number of requests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CodeBehind 4.8 also removed the &lt;code&gt;web_forms_view_place&lt;/code&gt; and &lt;code&gt;use_comment_mode_for_web_forms_combinate&lt;/code&gt; options as part of a cleaner and more reliable options architecture.&lt;/p&gt;

&lt;p&gt;These changes are not simply API cleanup. They reduce legacy paths and simplify framework behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Through Simplification
&lt;/h2&gt;

&lt;p&gt;Elanat has also been working toward a more consistent WebForms API across different programming languages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;WebForms&lt;/code&gt; class is available across multiple WebForms Core implementations. Removing language-specific behavior such as the old &lt;code&gt;Control&lt;/code&gt; pattern makes the API more consistent between implementations.&lt;/p&gt;

&lt;p&gt;This is useful not only from an API-design perspective but also from a maintenance and optimization perspective.&lt;/p&gt;

&lt;p&gt;A smaller and more consistent execution path is easier to optimize.&lt;/p&gt;

&lt;h2&gt;
  
  
  CodeBehind and ASP.NET MVC
&lt;/h2&gt;

&lt;p&gt;ASP.NET MVC remains one of the most established server-side web frameworks in the .NET ecosystem.&lt;/p&gt;

&lt;p&gt;The benchmark result does not mean that CodeBehind is faster than MVC in every possible application or workload. Real-world performance depends on application architecture, middleware, database access, serialization, network conditions, hardware, configuration, and the specific operations performed by an application.&lt;/p&gt;

&lt;p&gt;However, the benchmark provides a useful direct comparison under the same reported benchmark environment.&lt;/p&gt;

&lt;p&gt;In these results, CodeBehind consistently stays ahead of ASP.NET MVC:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;139,431 vs. 114,011 requests/s&lt;/strong&gt; at the 64-request test size,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;127,252 vs. 108,498 requests/s&lt;/strong&gt; at 256,&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;126,435 vs. 107,883 requests/s&lt;/strong&gt; at 512.&lt;/p&gt;

&lt;p&gt;The resulting average advantage is approximately &lt;strong&gt;19%&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Than a Benchmark Number
&lt;/h2&gt;

&lt;p&gt;For Elanat, the significance of this result is not simply the number itself.&lt;/p&gt;

&lt;p&gt;CodeBehind has been evolving through a series of architectural decisions aimed at reducing unnecessary work, simplifying execution paths, improving rendering behavior, and creating a more consistent server-side development model.&lt;/p&gt;

&lt;p&gt;The performance result is therefore better viewed as the outcome of continued optimization rather than a single performance trick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The latest Web Frameworks Benchmark shows that &lt;strong&gt;CodeBehind 4.8 is approximately 19% faster than ASP.NET MVC 10 on average across the three reported request sizes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The individual advantage ranges from &lt;strong&gt;17.2% to 22.3%&lt;/strong&gt;, with CodeBehind outperforming ASP.NET MVC in every tested case.&lt;/p&gt;

&lt;p&gt;At the same time, CodeBehind performs one-time View and Controller class generation and compilation during its initial execution. This additional work should be distinguished from steady-state request processing after compilation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/codebehind" rel="noopener noreferrer"&gt;Official CodeBehind Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/elanatframework/CodeBehind" rel="noopener noreferrer"&gt;CodeBehind Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NuGet:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/CodeBehind" rel="noopener noreferrer"&gt;CodeBehind Package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>performance</category>
      <category>backend</category>
    </item>
    <item>
      <title>Building a Bubble Popping Game with WebForms Core + Online Demo</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 15 Oct 2026 13:12:07 +0000</pubDate>
      <link>https://dev.to/elanatframework/building-a-bubble-popping-game-with-webforms-core-online-demo-1j2</link>
      <guid>https://dev.to/elanatframework/building-a-bubble-popping-game-with-webforms-core-online-demo-1j2</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core&lt;/a&gt; (WFC) is a server-side UI manipulation technology that lets developers control HTML elements and handle browser events through commands generated on the server. In this tutorial, we will use WebForms Core with C# and CodeBehind to build a simple bubble popping game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://webforms-core.github.io/demo/#bubble_popping_game" rel="noopener noreferrer"&gt;Bubble Popping Game&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The game demonstrates how to create HTML elements dynamically, attach events, update the score, run intervals, and detect when an element exceeds a specified width, all through WebForms Core commands.&lt;/p&gt;

&lt;p&gt;WebForms Core is a technology developed by &lt;a href="https://elanat.net" rel="noopener noreferrer"&gt;Elanat&lt;/a&gt; and is available in 18 programming languages.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; WebForms Core can be used to build simple to moderately complex games, including animated games and logic-based games such as Memory. For large or highly complex games, specialized technologies and tools, such as WebGL, WebGPU, and dedicated game engines, are recommended.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Defining the Game Interface
&lt;/h2&gt;

&lt;p&gt;The page contains a game area, a score counter, a speed counter, a message for the end of the game, and a button to start a new game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"GameArea"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;b&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Points"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Points: &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;b&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Speed"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Speed: &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;5&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;b&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Finall"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"PointsValue"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"SpeedValue"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Start"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Start New"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;GameArea&lt;/code&gt; element is the main container for the bubbles. The &lt;code&gt;Points&lt;/code&gt; and &lt;code&gt;Speed&lt;/code&gt; elements display the current game values, while the hidden inputs store those values so that WebForms Core commands can read and update them.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Start&lt;/code&gt; button restarts the game, and &lt;code&gt;Finall&lt;/code&gt; displays the player's final score when the game ends.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling the bubbles
&lt;/h3&gt;

&lt;p&gt;CSS gives the game its visual appearance. The game area uses a light blue background, while each bubble is a green circle with white curved lines to create a three-dimensional appearance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#GameArea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1280px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;720px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.bubblebox&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.bubble&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#c9e83b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-10px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.pusher&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.bubblebox&lt;/code&gt; class represents a row containing a pusher and a bubble. The &lt;code&gt;.pusher&lt;/code&gt; element occupies space before the bubble, allowing the bubble's horizontal position to change as the pusher grows.&lt;/p&gt;

&lt;p&gt;The remaining CSS uses &lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt; pseudo-elements to draw decorative curves inside each bubble. Attribute selectors such as &lt;code&gt;[bubblerow="1"]&lt;/code&gt; assign different top margins to different rows.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Initializing WebForms Core
&lt;/h2&gt;

&lt;p&gt;The main controller is &lt;code&gt;BubblePoppingGameController&lt;/code&gt;, which inherits from &lt;code&gt;CodeBehindController&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;CodeBehind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BubblePoppingGameController&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeBehindController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"GameArea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mutationobserver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Game commands are defined here.&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;WebForms&lt;/code&gt; class is used to define the commands that control the game.&lt;/p&gt;

&lt;p&gt;Two event configurations are especially important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SetCommentEventListener&lt;/code&gt; registers a MutationObserver-based listener for changes in &lt;code&gt;GameArea&lt;/code&gt;. The listener invokes the &lt;code&gt;end&lt;/code&gt; command index when the configured event condition is met.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SetCommentEvent&lt;/code&gt; associates the button's click event with the &lt;code&gt;start&lt;/code&gt; command index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The controller then defines the command sequences for starting, playing, and ending the game. WebForms Core exports these commands as HTML comments, which WebFormsJS processes in the browser.&lt;/p&gt;

&lt;p&gt;This approach allows the developer to define UI operations and event handling in C# without manually writing JavaScript for each interaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb06xlly6z60ihpqml9wk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb06xlly6z60ihpqml9wk.jpg" alt="WebForms Core Technology" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Starting a New Game
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;start&lt;/code&gt; command index initializes the game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PointsValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Points|&amp;lt;span&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PointsValue"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SpeedValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Speed|&amp;lt;span&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SpeedValue"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Initialization&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IncreaseWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{pusher}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AssignInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pusher"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each operation has a specific purpose.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;Reset()&lt;/code&gt; removes the existing game elements and stops the intervals from the previous game. The final-score message is cleared, and the score and speed values are restored to their initial values.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Fetch.GetValue()&lt;/code&gt; reads the value of a hidden input. The result is then used by &lt;code&gt;SetText()&lt;/code&gt; to update the corresponding display.&lt;/p&gt;

&lt;p&gt;Next, &lt;code&gt;Initialization()&lt;/code&gt; creates the first row and its bubble.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;IncreaseWidth()&lt;/code&gt; increases the width of the pusher, and &lt;code&gt;AssignInterval()&lt;/code&gt; schedules repeated execution of the command associated with the &lt;code&gt;pusher&lt;/code&gt; index.&lt;/p&gt;

&lt;p&gt;This is an important characteristic of WebForms Core: an interval can repeatedly execute a sequence of UI commands without requiring a custom JavaScript timer for the game logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Creating Bubbles Dynamically
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Initialization()&lt;/code&gt; method defines the structure of a bubble row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="nf"&gt;Initialization&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GameArea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"div"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"GameArea|&amp;lt;div&amp;gt;-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bubblebox"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"{bubblebox}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"bubblerow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{bubblebox}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"div"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"{bubblebox}-1|&amp;lt;div&amp;gt;-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pusher"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{bubblebox}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"div"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"{bubblebox}-1|&amp;lt;div&amp;gt;-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bubble"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"{bubble}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnMouseEnter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"popping"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Movement and overflow detection follow.&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method creates three elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;bubblebox&lt;/code&gt; container inside &lt;code&gt;GameArea&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;pusher&lt;/code&gt; element inside the container.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;bubble&lt;/code&gt; element beside the pusher.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;SetClass()&lt;/code&gt; assigns the CSS classes, while &lt;code&gt;SetAttribute()&lt;/code&gt; adds a &lt;code&gt;bubblerow&lt;/code&gt; attribute. &lt;code&gt;Fetch.Random(1, 8)&lt;/code&gt; supplies the row number used to determine the bubble's vertical placement.&lt;/p&gt;

&lt;p&gt;The last command associates the bubble's &lt;code&gt;mouseover&lt;/code&gt;-style event, &lt;code&gt;HtmlEvent.OnMouseEnter&lt;/code&gt;, with the &lt;code&gt;popping&lt;/code&gt; command index.&lt;/p&gt;

&lt;p&gt;When the pointer enters a bubble, WebForms Core can therefore execute the commands defined under &lt;code&gt;popping&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important point is that the bubble elements are created dynamically. They do not need to be written individually into the original HTML page.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Moving the Bubble
&lt;/h2&gt;

&lt;p&gt;The pusher controls the bubble's horizontal position. Its width increases over time, making the bubble move across the game area.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IncreaseWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{pusher}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AssignInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pusher-pluse"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;pusher-pluse&lt;/code&gt; command index increases the pusher's width by one unit. The interval is assigned a delay of 10 milliseconds.&lt;/p&gt;

&lt;p&gt;When the game starts, the &lt;code&gt;pusher&lt;/code&gt; index is also assigned a 100-millisecond interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IncreaseWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{pusher}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AssignInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pusher"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two intervals perform different roles: &lt;code&gt;pusher-pluse&lt;/code&gt; controls the continuous growth of the pusher, while &lt;code&gt;pusher&lt;/code&gt; is the separate interval configured during game initialization.&lt;/p&gt;

&lt;p&gt;The game also needs to detect when the pusher grows too large. WebForms Core provides a custom DOM event for this purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateCustomDOMEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"{pusher}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"widthOverflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"greater"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"1100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"{pusher}-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"widthOverflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The custom event monitors the pusher's &lt;code&gt;width&lt;/code&gt; style and checks whether it exceeds &lt;code&gt;1100&lt;/code&gt;. Its configuration also includes the event options &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;widthOverflow&lt;/code&gt; occurs, the listener invokes the &lt;code&gt;end&lt;/code&gt; command index. This connects the movement logic to the end-of-game logic without requiring a manually written JavaScript event handler.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Popping a Bubble and Updating the Score
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;popping&lt;/code&gt; command index defines what happens when the player touches a bubble.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"popping"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IncreaseValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PointsValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Points|&amp;lt;span&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PointsValue"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IncreaseValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SpeedValue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Speed|&amp;lt;span&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SpeedValue"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Initialization&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, &lt;code&gt;IncreaseValue()&lt;/code&gt; increments the score stored in &lt;code&gt;PointsValue&lt;/code&gt;. &lt;code&gt;Fetch.GetValue()&lt;/code&gt; retrieves the updated value, and &lt;code&gt;SetText()&lt;/code&gt; refreshes the score shown on the page.&lt;/p&gt;

&lt;p&gt;The speed value is updated in the same way. Each successful bubble interaction increases it by one and refreshes the display.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;Delete("$/")&lt;/code&gt; removes the element selected by that input-place expression. The game then calls &lt;code&gt;Initialization()&lt;/code&gt; again, creating another bubble row.&lt;/p&gt;

&lt;p&gt;Consequently, a successful interaction updates the counters, removes the targeted element, and creates another bubble. The player can continue interacting with bubbles until the overflow event ends the game.&lt;/p&gt;

&lt;p&gt;In this implementation, the speed counter is incremented as a displayed value, but the interval delays themselves remain fixed at 100 and 10 milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Ending the Game
&lt;/h2&gt;

&lt;p&gt;When the overflow listener invokes the &lt;code&gt;end&lt;/code&gt; command index, the controller displays the final score and resets the game elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Finall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"@:Your point is: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Points|&amp;lt;span&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Fetch.GetText()&lt;/code&gt; reads the displayed score, and &lt;code&gt;Inject()&lt;/code&gt; inserts the retrieved text into the command being constructed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SetText()&lt;/code&gt; then displays the final-score message inside &lt;code&gt;Finall&lt;/code&gt;. The &lt;code&gt;Reset()&lt;/code&gt; method removes the game elements and stops the intervals.&lt;/p&gt;

&lt;p&gt;The reset method is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="nf"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ElementExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GameArea|&amp;lt;div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GameArea|&amp;lt;div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DeleteInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pusher"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DeleteInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pusher-pluse"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The element-existence check precedes the deletion of the game rows. The method also removes both named intervals, preventing the previous game's movement commands from continuing after a restart or game end.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Start New&lt;/code&gt; button can then execute the &lt;code&gt;start&lt;/code&gt; command index to initialize a fresh game.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Exporting the Commands
&lt;/h2&gt;

&lt;p&gt;At the end of &lt;code&gt;PageLoad()&lt;/code&gt;, the controller exports the commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This writes the WebForms Core command representation as HTML comments in the response.&lt;/p&gt;

&lt;p&gt;WebFormsJS processes these comments in the browser and executes the corresponding operations against the actual HTML DOM. The server defines the command sequences, while the client executes them.&lt;/p&gt;

&lt;p&gt;The result is a game whose interface is built and manipulated through WebForms Core rather than through a collection of hand-written JavaScript DOM operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screenshot of Bubble Popping Game&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F36k6ylhrizpzrwd5x22u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F36k6ylhrizpzrwd5x22u.png" alt="Create Game with WebForms Core Technology" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Bubble Popping Game demonstrates several practical WebForms Core capabilities in a single example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically creating HTML elements and assigning CSS classes and attributes.&lt;/li&gt;
&lt;li&gt;Connecting browser events to named command indexes.&lt;/li&gt;
&lt;li&gt;Updating values and displayed text.&lt;/li&gt;
&lt;li&gt;Executing repeated commands through intervals.&lt;/li&gt;
&lt;li&gt;Detecting DOM conditions through custom events.&lt;/li&gt;
&lt;li&gt;Removing elements, stopping intervals, and restarting the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features make it possible to implement interactive browser experiences using C# and WebForms Core, with WebFormsJS executing the generated commands in the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try the game:&lt;/strong&gt; &lt;a href="https://webforms-core.github.io/demo/#bubble_popping_game" rel="noopener noreferrer"&gt;Open the Bubble Popping Game demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>game</category>
      <category>gamedev</category>
      <category>webdev</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>CSRF Protection in WebForms Core Using CodeBehind</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Sat, 10 Oct 2026 16:03:18 +0000</pubDate>
      <link>https://dev.to/elanatframework/csrf-protection-in-webforms-core-using-codebehind-3h26</link>
      <guid>https://dev.to/elanatframework/csrf-protection-in-webforms-core-using-codebehind-3h26</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction to CSRF Protection in WebForms Core
&lt;/h2&gt;

&lt;p&gt;Cross-Site Request Forgery (CSRF) is a web security vulnerability in which an attacker tricks a user's browser into sending an unwanted request to a website where the user is authenticated. If the website relies on automatically attached authentication cookies without properly verifying the request, an attacker may be able to trigger actions on behalf of the victim.&lt;/p&gt;

&lt;p&gt;WebForms Core (WFC), introduced by Elanat, provides a server-oriented approach to web interface manipulation. The backend generates commands that WebFormsJS executes in the browser, allowing web interfaces to be manipulated through server-generated instructions without requiring a separate frontend framework.&lt;/p&gt;

&lt;p&gt;In this article, we will implement a basic CSRF protection mechanism using WebForms Core and CodeBehind, a backend web framework developed by Elanat. We will generate a secure token, store it in a session, add it to an HTML form, and validate it when the form is submitted.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. CodeBehind as the Backend
&lt;/h2&gt;

&lt;p&gt;CodeBehind handles HTTP requests, manages the session-based CSRF token, validates submitted data, and generates responses through WebForms Core.&lt;/p&gt;

&lt;p&gt;The process follows this sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The browser requests the page.&lt;/li&gt;
&lt;li&gt;CodeBehind retrieves an existing CSRF token from the session or generates a new one.&lt;/li&gt;
&lt;li&gt;WebForms Core adds the token to the HTML form as a hidden input.&lt;/li&gt;
&lt;li&gt;The browser submits the form with the token.&lt;/li&gt;
&lt;li&gt;CodeBehind compares the submitted token with the token stored in the session.&lt;/li&gt;
&lt;li&gt;WebForms Core generates commands to display the validation result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The security decision takes place on the backend. WebFormsJS executes the resulting interface commands, but it does not determine whether the CSRF token is valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generating a Secure CSRF Token
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d4133alcendrggx9a78.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7d4133alcendrggx9a78.jpg" alt="WebForms Core Security" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A CSRF token must be unpredictable so that an attacker cannot easily construct a valid request. C# provides &lt;code&gt;RandomNumberGenerator&lt;/code&gt;, which is designed for cryptographically secure random number generation.&lt;/p&gt;

&lt;p&gt;The following code generates a token from 32 random bytes and converts it into a hexadecimal string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Security.Cryptography&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Convert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToHexString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;RandomNumberGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces a 64-character hexadecimal token representing 256 bits of random data.&lt;/p&gt;

&lt;p&gt;Unlike a token generated with the ordinary &lt;code&gt;Random&lt;/code&gt; class, this value is suitable for security-sensitive purposes. The token should be generated on the server and must not be predictable from public information such as usernames, timestamps, or sequential identifiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Storing the Token in Session
&lt;/h2&gt;

&lt;p&gt;The token must remain available between the initial page request and the subsequent form submission. In this example, ASP.NET Core Session provides the required storage.&lt;/p&gt;

&lt;p&gt;The following method retrieves the existing token or generates and stores one if it does not exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetCsrfToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Convert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToHexString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;RandomNumberGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The session allows the server to associate the token with the user's session and retrieve it when the form is submitted. Session services and middleware must be configured correctly in the ASP.NET Core application.&lt;/p&gt;

&lt;p&gt;The session cookie should also be protected with appropriate security settings, including HTTPS and suitable cookie attributes.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Adding the Token to the HTML Form with WebForms Core
&lt;/h2&gt;

&lt;p&gt;The CSRF token is included in the form as a hidden input. WebForms Core can generate the required interface command without requiring a separate JavaScript operation to create the field.&lt;/p&gt;

&lt;p&gt;The example form is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/security_csrf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email: &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Update Email&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the CodeBehind controller, the token is added to the form using WebForms Core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHidden&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;form&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AddHidden&lt;/code&gt; targets the form and adds a hidden field named &lt;code&gt;csrf_token&lt;/code&gt;. &lt;code&gt;ExportToHtmlComment()&lt;/code&gt; exports the WebForms Core commands in the format expected by the client-side executor.&lt;/p&gt;

&lt;p&gt;To execute WebForms Core commands in the browser, the page must also include the WebFormsJS client-side library. For example, if the library is located at &lt;code&gt;/script/web-forms.js&lt;/code&gt;, add the following script to the HTML document's &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/script/web-forms.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the script path to match the location of the WebFormsJS file in your application.&lt;/p&gt;

&lt;p&gt;The browser submits the hidden token along with the other form fields. Although the token is not visible in the interface, it is accessible to the page and must not be treated as a secret from JavaScript executing in that page. Its security depends on its unpredictability and server-side validation, not on the hidden field itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full page management code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetCsrfToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Button_Click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHidden&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;form&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Validating CSRF Tokens on POST Requests
&lt;/h2&gt;

&lt;p&gt;When the form is submitted, CodeBehind retrieves the token from the request and compares it with the token stored in the session.&lt;/p&gt;

&lt;p&gt;The following example checks that both values are non-empty before comparing them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;formToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="n"&gt;formToken&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Continue with the protected operation.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Reject the protected operation.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking both values is important. If the session token is missing or the submitted form does not contain a token, the request must not be accepted.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;==&lt;/code&gt; comparison makes the basic validation logic easy to understand. For applications requiring stronger protection against timing-based comparison attacks, a fixed-time comparison can be used instead, as discussed in the final section.&lt;/p&gt;

&lt;p&gt;A successful comparison means that the request contains the expected session token. It does not replace authentication, authorization, or validation of the submitted email address.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Handling Validation Results with WebForms Core
&lt;/h2&gt;

&lt;p&gt;After validating the token, the controller uses WebForms Core to generate a response that communicates the result to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Button_Click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;formToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"csrf_token"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;formToken&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"CSRF token validation succeeded."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Your Email is: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Security&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;SafeValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Security check failed. Please refresh the page and try again."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"warning"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;IgnoreAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Transition by bypassing View and Layout&lt;/span&gt;
    &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example uses &lt;code&gt;new Security().SafeValue(email)&lt;/code&gt; before including the submitted email in a message. This is intended to prevent untrusted email content from injecting executable HTML or script content into the interface. It is important to use the appropriate output-safety method for the rendering context and avoid encoding the same content twice.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Message&lt;/code&gt; generates the interface feedback, while &lt;code&gt;Response()&lt;/code&gt; generates the WebForms Core response. &lt;code&gt;IgnoreAll()&lt;/code&gt; bypasses the view and layout for this response, allowing the command response to be returned directly.&lt;/p&gt;

&lt;p&gt;This demonstrates the separation between security decisions and interface updates: CodeBehind validates the request on the server, WebForms Core generates the commands, and WebFormsJS executes them in the browser.&lt;/p&gt;

&lt;p&gt;The application does not have to return an HTTP &lt;code&gt;403&lt;/code&gt; status solely to display a validation warning. In this command-response workflow, a normal response can preserve Action Control execution. The essential requirement is that the protected operation must never run when validation fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Additional Security Layers and Conclusion
&lt;/h2&gt;

&lt;p&gt;A session-based CSRF token is an important protection, but it should be part of a broader security strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed-time token comparison&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For additional protection, the simple &lt;code&gt;==&lt;/code&gt; comparison can be replaced with &lt;code&gt;CryptographicOperations.FixedTimeEquals&lt;/code&gt;. This method compares equal-length byte arrays in a way designed to reduce information leakage through timing differences.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;FixedTimeEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;aBytes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;bBytes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aBytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;bBytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CryptographicOperations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FixedTimeEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;aBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The empty-value checks ensure that two missing tokens are never treated as a successful match. The length check ensures that the comparison receives byte arrays of equal length.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other security measures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Depending on the application, additional measures can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Origin validation:&lt;/strong&gt; Check the &lt;code&gt;Origin&lt;/code&gt; header against the expected origin for state-changing requests. A carefully implemented &lt;code&gt;Referer&lt;/code&gt; check can be used as a fallback when appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SameSite cookies:&lt;/strong&gt; Configure authentication cookies with an appropriate &lt;code&gt;SameSite&lt;/code&gt; policy, such as &lt;code&gt;Lax&lt;/code&gt; or &lt;code&gt;Strict,&lt;/code&gt; according to the application's requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTPS:&lt;/strong&gt; Protect session cookies and requests in transit using HTTPS and suitable secure-cookie settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication and authorization:&lt;/strong&gt; Verify that the user is authenticated and permitted to perform the requested operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input validation and output safety:&lt;/strong&gt; Validate submitted data and use &lt;code&gt;Security.SafeValue&lt;/code&gt; or another appropriate context-specific output-encoding mechanism when displaying untrusted content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These measures complement one another. Origin validation and SameSite cookies provide additional layers of defense, but they should not automatically be treated as replacements for CSRF token validation where it is required.&lt;/p&gt;

&lt;p&gt;With CodeBehind handling the backend logic and WebForms Core managing server-generated interface commands, CSRF protection fits naturally into a server-oriented web application. The security decision remains on the server, while the resulting feedback is delivered through the WebForms Core response mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;Official WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;Official WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/codebehind" rel="noopener noreferrer"&gt;Official CodeBehind Framework Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;WebForms Core Demo Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/elanatframework/CodeBehind" rel="noopener noreferrer"&gt;CodeBehind Framework Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>csrf</category>
      <category>cybersecurity</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>Drag and Drop Without Writing JavaScript with WFC + Online Demo</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Thu, 08 Oct 2026 12:43:58 +0000</pubDate>
      <link>https://dev.to/elanatframework/drag-and-drop-without-writing-javascript-with-wfc-online-demo-ejk</link>
      <guid>https://dev.to/elanatframework/drag-and-drop-without-writing-javascript-with-wfc-online-demo-ejk</guid>
      <description>&lt;p&gt;Drag and Drop interactions are usually implemented with client-side JavaScript. Developers typically need to listen for pointer events, track the dragged element, prevent default browser behavior, update CSS classes, and finally move or remove the element.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;WebForms Core (WFC)&lt;/strong&gt;, the same interaction can be implemented by defining events and commands on the server. No custom JavaScript event handlers are required.&lt;/p&gt;

&lt;p&gt;The following example uses Node.js and Express.&lt;/p&gt;

&lt;p&gt;It is recommended to view the drag-and-drop demo before looking at the code.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://webforms-core.github.io/demo/#drag_and_drop" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;webforms-core.github.io&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The Example
&lt;/h2&gt;

&lt;p&gt;The page contains two zones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dragZone&lt;/code&gt; contains draggable elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dropZone&lt;/code&gt; is the destination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an item is dragged with a mouse, it can be moved between the two zones. On touch devices, where native HTML Drag and Drop is not normally suitable, a direct tap can be used to move an item between the zones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./WebForms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|&amp;lt;div&amp;gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragStart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragEnd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPreventDefaultEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragOver&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragOver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-over-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragLeave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-leave-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDrop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPreventDefaultEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragOver&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragOver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-over&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragLeave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-leave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDrop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|&amp;lt;div&amp;gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnTouchStart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;touch-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hide&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assignDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-over&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-leave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-over-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-leave-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;touch-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;elementExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|{{id}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assignReplace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{id}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
        &amp;lt;!DOCTYPE html&amp;gt;
        &amp;lt;html&amp;gt;
        &amp;lt;head&amp;gt;
          &amp;lt;title&amp;gt;Drag and Drop - WebForms Core&amp;lt;/title&amp;gt;
          &amp;lt;script type="module" src="/script/web-forms.js"&amp;gt;&amp;lt;/script&amp;gt;

          &amp;lt;style&amp;gt;
            #dropZone, #dragZone {
                width: 100%;
                max-width: 600px;
                height: auto;
                min-height: 200px;
                border: 2px dashed #ccc;
                border-radius: 5px;
                text-align: center;
                padding: 20px;
                margin: 20px auto;
            }

            #dropZone.highlight, #dragZone.highlight {
                border-color: #4CAF50;
                background-color: #f8f8f8;
            }

            .dragitem {
                width: 100px;
                height: 100px;
                background-color: #4CAF50;
                color: white;
                text-align: center;
                line-height: 100px;
                cursor: move;
                margin: 20px auto;
            }

            .hide {
                display: none;
            }
          &amp;lt;/style&amp;gt;
        &amp;lt;/head&amp;gt;

        &amp;lt;body&amp;gt;
            &amp;lt;h2&amp;gt;Drag and Drop&amp;lt;/h2&amp;gt;

            &amp;lt;blockquote&amp;gt;
                With a mouse, items are moved via drag and drop;
                with touch, they are moved by a direct tap.
            &amp;lt;/blockquote&amp;gt;

            &amp;lt;div id="dragZone"&amp;gt;
                &amp;lt;div class="dragitem" id="dragitem1" draggable="true"&amp;gt;Drag me! 1&amp;lt;/div&amp;gt;
                &amp;lt;div class="dragitem" id="dragitem2" draggable="true"&amp;gt;Drag me! 2&amp;lt;/div&amp;gt;
                &amp;lt;div class="dragitem" id="dragitem3" draggable="true"&amp;gt;Drag me! 3&amp;lt;/div&amp;gt;
                &amp;lt;div class="dragitem" id="dragitem4" draggable="true"&amp;gt;Drag me! 4&amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div id="dropZone"&amp;gt;Drop here&amp;lt;/div&amp;gt;

            &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;
        &amp;lt;/body&amp;gt;
        &amp;lt;/html&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on http://localhost:3000`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining the Drag Events
&lt;/h2&gt;

&lt;p&gt;The first step is to associate WebForms Core events with the draggable elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|&amp;lt;div&amp;gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragStart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnDragEnd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dragZone|&amp;lt;div&amp;gt;*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;targets the &lt;code&gt;div&lt;/code&gt; elements inside &lt;code&gt;dragZone&lt;/code&gt;. Each of these elements can therefore participate in the same drag behavior.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-&lt;/code&gt; input place refers to the event target, allowing the same command sequence to operate on the element that triggered the event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving the Dragged Element
&lt;/h2&gt;

&lt;p&gt;When dragging starts, the example stores two pieces of information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The outer text is saved so it can later be inserted into another zone, while the element's ID is saved as &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is important because the server-generated commands can later use the saved values without requiring custom client-side JavaScript variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Highlighting the Drop Zone
&lt;/h2&gt;

&lt;p&gt;While the user is dragging an item over the destination, the destination receives a visual highlight:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-over&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the pointer leaves the zone, the class is removed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drag-leave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;highlight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same mechanism is used for the original &lt;code&gt;dragZone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means the visual state is controlled through WebForms Core commands rather than through a JavaScript event handler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving the Item
&lt;/h2&gt;

&lt;p&gt;The actual drop operation is particularly simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sequence performs two operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove the original element using its saved ID.&lt;/li&gt;
&lt;li&gt;Add its saved content to &lt;code&gt;dropZone&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important point is that these are &lt;strong&gt;DOM manipulation commands generated by the server-side WebForms class&lt;/strong&gt;. There is no client-side &lt;code&gt;dragstart&lt;/code&gt;, &lt;code&gt;dragover&lt;/code&gt;, or &lt;code&gt;drop&lt;/code&gt; function written by the developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supporting the Reverse Direction
&lt;/h2&gt;

&lt;p&gt;The same mechanism works when moving an element back from &lt;code&gt;dropZone&lt;/code&gt; to &lt;code&gt;dragZone&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop-back&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The destination changes, but the basic operation remains the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Delete original element → Add its content to destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Touch Interaction Without JavaScript
&lt;/h2&gt;

&lt;p&gt;Native HTML Drag and Drop is primarily designed around pointer-based dragging and is not a reliable interaction model for touch devices.&lt;/p&gt;

&lt;p&gt;Instead of implementing a separate JavaScript touch system, this example defines a WebForms Core &lt;code&gt;OnTouchStart&lt;/code&gt; event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|&amp;lt;div&amp;gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OnTouchStart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;touch-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The touch behavior is then implemented with WebForms Core commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;touch-start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;elementExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone|{{id}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assignReplace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{id}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragZone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOuterText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Screenshot of Drag &amp;amp; Drop Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyjg1rsp9412ecb0wnafy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyjg1rsp9412ecb0wnafy.png" alt="Drag &amp;amp; Drop WebForms Core" width="706" height="789"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The logic is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the touched element already exists in &lt;code&gt;dragZone&lt;/code&gt;, move it to &lt;code&gt;dropZone&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, move it back to &lt;code&gt;dragZone&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, a touch interaction can provide a simple toggle between the two zones without implementing a custom JavaScript drag-and-drop engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Server-Side Definition, Multiple Client Behaviors
&lt;/h2&gt;

&lt;p&gt;The example demonstrates an important aspect of WebForms Core.&lt;/p&gt;

&lt;p&gt;The developer describes the interaction on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event
    ↓
WebForms command sequence
    ↓
WebFormsJS
    ↓
HTML DOM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WebFormsJS executes the commands in the browser. It does not require the developer to write separate JavaScript functions for each event.&lt;/p&gt;

&lt;p&gt;The application therefore does not contain code such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragstart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragover&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dragleave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;drop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;touchstart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, the interaction is declared through the server-side &lt;code&gt;WebForms&lt;/code&gt; class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Different
&lt;/h2&gt;

&lt;p&gt;A conventional implementation usually requires the developer to create a client-side interaction layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTML
  ↓
JavaScript event handlers
  ↓
Application state
  ↓
DOM manipulation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With WebForms Core, the interaction can be expressed as server-defined commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server
  ↓
WebForms
  ↓
WebForms Core commands
  ↓
WebFormsJS
  ↓
HTML DOM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser still performs the actual DOM operations, but the developer does not need to implement those operations as custom JavaScript code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F94f8onpac6veot5o6bcq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F94f8onpac6veot5o6bcq.jpg" alt="WebForms Core" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is particularly useful for applications where interaction logic is already organized around server-side controls and commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Custom JavaScript Required
&lt;/h2&gt;

&lt;p&gt;The only JavaScript referenced by the page is the WebFormsJS executor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/script/web-forms.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no custom JavaScript file containing drag-and-drop handlers.&lt;/p&gt;

&lt;p&gt;The HTML remains ordinary HTML, and the draggable elements use the standard &lt;code&gt;draggable&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dragitem"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"dragitem1"&lt;/span&gt; &lt;span class="na"&gt;draggable=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Drag me! 1
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interaction logic is defined entirely through the server-side &lt;code&gt;WebForms&lt;/code&gt; API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This example shows that Drag and Drop does not necessarily require a custom JavaScript implementation.&lt;/p&gt;

&lt;p&gt;With WebForms Core, mouse-based Drag and Drop can be defined through standard HTML events and server-generated commands, while touch interaction can be handled through a separate &lt;code&gt;OnTouchStart&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;The result is a server-orchestrated interaction where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the server defines the behavior,&lt;/li&gt;
&lt;li&gt;WebForms Core generates the commands,&lt;/li&gt;
&lt;li&gt;WebFormsJS executes those commands,&lt;/li&gt;
&lt;li&gt;and the browser performs the final DOM operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, the developer does not have to write a JavaScript Drag and Drop implementation or maintain a separate client-side interaction layer.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to ask.&lt;br&gt;
If you have any comments, please share them.&lt;br&gt;
We will gladly answer!&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;Official WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;Official WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;WebForms Core Demo Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>discuss</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>No React, No Vue, No Angular: Explore the WebForms Core Demo Website in Action</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Tue, 06 Oct 2026 22:05:44 +0000</pubDate>
      <link>https://dev.to/elanatframework/no-react-no-vue-no-angular-explore-the-webforms-core-demo-website-in-action-39lj</link>
      <guid>https://dev.to/elanatframework/no-react-no-vue-no-angular-explore-the-webforms-core-demo-website-in-action-39lj</guid>
      <description>&lt;p&gt;The new &lt;strong&gt;WebForms Core Demo&lt;/strong&gt; is now available:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;https://webforms-core.github.io/demo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Explore WebForms Core through interactive examples and see how server-orchestrated UI works in practice.&lt;/p&gt;

&lt;p&gt;The demo includes examples of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chart using an extension method&lt;/li&gt;
&lt;li&gt;Custom DOM events&lt;/li&gt;
&lt;li&gt;Value formatting&lt;/li&gt;
&lt;li&gt;Server-driven rendering with &lt;strong&gt;Render&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Interactive applications such as a Memory Tiles game&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core&lt;/a&gt; uses a &lt;strong&gt;Commander–Executor&lt;/strong&gt; architecture. The WebForms class generates commands, and WebFormsJS executes them directly on the HTML DOM. The server is &lt;strong&gt;stateless&lt;/strong&gt;, while routing and UI infrastructure are handled &lt;strong&gt;automatically&lt;/strong&gt;, allowing developers to focus on writing the application logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhhcqxstp9qqs6sx1w0go.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhhcqxstp9qqs6sx1w0go.png" alt="WebForms Core Demo Website" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No React. No Vue. No Angular. No JSX.&lt;/p&gt;

&lt;p&gt;Just server-generated commands and direct DOM execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try the demo now:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://webforms-core.github.io/demo" rel="noopener noreferrer"&gt;https://webforms-core.github.io/demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source code&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/webforms-core/demo" rel="noopener noreferrer"&gt;https://github.com/webforms-core/demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>vue</category>
      <category>angular</category>
      <category>webformscore</category>
    </item>
    <item>
      <title>Have You Used WebForms Core? Share Your Experience</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:26:55 +0000</pubDate>
      <link>https://dev.to/elanatframework/have-you-used-webforms-core-share-your-experience-55d9</link>
      <guid>https://dev.to/elanatframework/have-you-used-webforms-core-share-your-experience-55d9</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core&lt;/a&gt; is launching on &lt;strong&gt;Product Hunt&lt;/strong&gt; on October 7.&lt;/p&gt;

&lt;p&gt;If you have already used WebForms Core, I’d really appreciate you sharing your experience and opinion when the launch goes live (October 7).&lt;/p&gt;

&lt;p&gt;What did you like? What could be improved? How did you use it in your projects?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffyroeue6q1isbijnoc5m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffyroeue6q1isbijnoc5m.jpg" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your feedback as someone who has actually used WebForms Core is especially valuable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/products/webforms-core" rel="noopener noreferrer"&gt;WebForms Core on Product Hunt&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>programming</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>WebForms Core 2.2 Released: Render, a New Approach to UI Rendering</title>
      <dc:creator>Elanat Framework</dc:creator>
      <pubDate>Sun, 04 Oct 2026 12:59:10 +0000</pubDate>
      <link>https://dev.to/elanatframework/webforms-core-22-released-render-a-new-approach-to-ui-rendering-5fg6</link>
      <guid>https://dev.to/elanatframework/webforms-core-22-released-render-a-new-approach-to-ui-rendering-5fg6</guid>
      <description>&lt;p&gt;&lt;strong&gt;WebForms Core&lt;/strong&gt; is a modern, server-orchestrated technology for building interactive HTML user interfaces, introduced by &lt;strong&gt;Elanat&lt;/strong&gt; in 2024. It enables direct and deterministic DOM management from the server, eliminating the need for separate client-side frameworks such as React, Vue, or Angular.&lt;/p&gt;

&lt;p&gt;WebForms Core 2.2 has been released.&lt;/p&gt;

&lt;p&gt;This release introduces several new capabilities, but one feature deserves special attention: &lt;strong&gt;Render&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Render is a high-level UI rendering primitive designed to make repeated server-side rendering of an existing HTML element predictable and manageable. It brings together several mechanisms that are all new in this version—&lt;strong&gt;Snapshot&lt;/strong&gt;, &lt;strong&gt;Rollback&lt;/strong&gt;, and &lt;strong&gt;Transient DOM&lt;/strong&gt;—into a single high-level primitive.&lt;/p&gt;

&lt;p&gt;The result is a simpler way to replace, rebuild, and restore parts of an HTML document while keeping the operation under server-side control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Render
&lt;/h2&gt;

&lt;p&gt;In this new version, &lt;code&gt;Snapshot&lt;/code&gt;, &lt;code&gt;Rollback&lt;/code&gt;, and &lt;code&gt;Render&lt;/code&gt; are all new additions. &lt;code&gt;Render&lt;/code&gt; is a high-level method that uses &lt;code&gt;Snapshot&lt;/code&gt; and &lt;code&gt;Rollback&lt;/code&gt; internally.&lt;/p&gt;

&lt;p&gt;In WebForms Core 2.2, Render brings these operations together.&lt;/p&gt;

&lt;p&gt;A simple example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{name}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{email}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{phone}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{age}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{city}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{country}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rendering process can also be used directly with a template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BindJSONToTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{value}}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is not simply the number of lines saved by Render. The important part is that the lifecycle of the rendered element is handled as one operation.&lt;/p&gt;

&lt;p&gt;Internally, Render checks whether a previous version of the selected element already exists. If it does, that version is restored. Otherwise, a Snapshot is created.&lt;/p&gt;

&lt;p&gt;The rendering process then enters the &lt;strong&gt;Transient DOM&lt;/strong&gt;, appends the generated WebForms commands, exits the Transient DOM, and appends the new form.&lt;/p&gt;

&lt;p&gt;In simplified form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Existing State
      ↓
Rollback or Snapshot
      ↓
Start Transient DOM
      ↓
Apply New Rendering
      ↓
End Transient DOM
      ↓
New UI State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly useful when the same element has to be rendered repeatedly with different data or templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Render and Transient DOM
&lt;/h3&gt;

&lt;p&gt;Render uses the Transient DOM internally.&lt;/p&gt;

&lt;p&gt;This is important when selecting &lt;code&gt;InputPlace&lt;/code&gt; values inside the Render operation. The root of the selected &lt;code&gt;InputPlace&lt;/code&gt; must be considered relative to the Transient DOM being processed.&lt;/p&gt;

&lt;p&gt;Render is therefore not simply a shortcut for a sequence of unrelated commands. It creates a controlled rendering process in which the existing state and the new state can be handled together.&lt;/p&gt;

&lt;p&gt;The implementation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The Render Method is Sensitive to DOM Changes; It is Recommended to Assign a Stable ID to the Selected Element.&lt;/span&gt;
&lt;span class="c1"&gt;// This Method Utilizes the Transient DOM; Therefore, When Selecting InputPlaces, You Must Consider the Root of the Selected InputPlace Within the Method.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="nf"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newForm&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;bodyData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetWebFormsData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bodyData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Permanent&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Else&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartTransientDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EndTransientDOM&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;AppendForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is also a configuration-based overload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="nf"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;newForm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes Render suitable for both manually constructed WebForms and dynamically configured rendering operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Snapshot and Rollback
&lt;/h2&gt;

&lt;p&gt;Render is built on top of the Snapshot and Rollback mechanisms introduced in WebForms Core 2.2.&lt;/p&gt;

&lt;p&gt;A Snapshot stores the state of a selected tag so that it can later be restored.&lt;/p&gt;

&lt;p&gt;Consider a simple multilingual user template.&lt;/p&gt;

&lt;p&gt;The page contains three buttons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"English"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"en-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Spanish"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"es-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Persian"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"fa-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The templates are defined using HTML &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"en-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Name: {{name}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:{{email}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email: {{email}}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Phone: {{phone}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Age: {{age}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;City: {{city}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Country: {{country}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"es-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Nombre: {{name}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:{{email}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Correo electrónico: {{email}}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Teléfono: {{phone}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Edad: {{age}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;Ciudad: {{city}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;País: {{country}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"fa-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;نام: {{name}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:{{email}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;ایمیل: {{email}}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;تلفن: {{phone}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;سن: {{age}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;شهر: {{city}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;field&amp;gt;&lt;/span&gt;کشور: {{country}}&lt;span class="nt"&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebForms code creates a Snapshot for each template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;CodeBehind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SnapshotAndRollbackController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeBehindController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"en-user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"es-user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fa-user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"set-state"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"set-state"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{name}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{email}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{phone}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{age}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{city}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{{country}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When one of the buttons is clicked, the corresponding Snapshot is restored and the user data is inserted into the selected template.&lt;/p&gt;

&lt;p&gt;The API itself is intentionally small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;InputPlace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Permanent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Snapshot and Rollback mechanism is sensitive to DOM changes, so assigning a stable ID to the selected element is recommended.&lt;/p&gt;

&lt;p&gt;Render uses these mechanisms automatically, so developers do not need to manually coordinate Snapshot and Rollback when using the high-level rendering API.&lt;/p&gt;

&lt;h2&gt;
  
  
  GetTagHash
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 also introduces &lt;code&gt;Fetch.GetTagHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It calculates a hash from the &lt;code&gt;outerHTML&lt;/code&gt; of a tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"GetHash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"get-hash"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"get-hash"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"-a"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTagHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Box"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hash is based only on the tag's &lt;code&gt;outerHTML&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This makes it useful for detecting whether the DOM representation of a tag has changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatting Values with Regex
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SetFormatCacheValue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SetFormatSaveValue&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These methods apply Regex-based formatting to values stored in Cache or Save.&lt;/p&gt;

&lt;p&gt;For example, the following page contains a money value and a time value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"SetFormat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click to Set Format&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Money"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"12345678"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Clock"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"15:1:3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebForms code stores each value and applies a regular-expression replacement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;CodeBehind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SetFormatController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeBehindController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"SetFormat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"set-format"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"set-format"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Money"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"money"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetFormatSaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"money"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"(\\d)(?=(\\d{3})+$)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"$$1,"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Money"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"money"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CacheValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Clock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"clock"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetFormatCacheValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"clock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"(^|:)(\\d)(?=:|$)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"$$10$2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Two $$ for escape JavaScript interpretation&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Clock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"clock"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first operation formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;12345678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;12,345,678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second transforms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15:1:3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15:01:03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;$$&lt;/code&gt; in the replacement string is important because it escapes the &lt;code&gt;$&lt;/code&gt; for JavaScript interpretation.&lt;/p&gt;

&lt;p&gt;This is also useful when formatting must happen as part of a larger WebForms operation, where the formatted value can then be applied back to the corresponding HTML element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arithmetic Operations
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 adds arithmetic operations for values stored in Cache and Save.&lt;/p&gt;

&lt;p&gt;The supported operations are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+
-
*
/
%
//
**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following example provides a button for each operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Addition"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Subtraction"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Multiplication"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;*&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Division"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Remainder"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;%&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"FloorDivision"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;//&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Power"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;**&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Value1"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; |
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Value2"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
=
&lt;span class="nt"&gt;&amp;lt;b&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Result"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebForms code is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;CodeBehind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArithmeticController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeBehindController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;button&amp;gt;*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetArithmeticSaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value2"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;//&lt;/code&gt; operation is implemented in WebFormsJS as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;//&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, with &lt;code&gt;10&lt;/code&gt; and &lt;code&gt;7&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt; produces the normal division result, while &lt;code&gt;//&lt;/code&gt; produces the floored result.&lt;/p&gt;

&lt;p&gt;The operations allow common numerical transformations to be performed directly within the WebForms command flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Text Operations
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 currently provides six text operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;textafter
textafterlast
textbefore
textbeforelast
substring
remove
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example below provides a button for each operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;textafter&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;textafterlast&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;textbefore&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;textbeforelast&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;substring&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;remove&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Value1"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"This is a Hello World!"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; |
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Value2"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; |
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Value3"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
=
&lt;span class="nt"&gt;&amp;lt;b&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Result"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebForms implementation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;CodeBehind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TextOperationController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CodeBehindController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PageLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;WebForms&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WebForms&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"&amp;lt;button&amp;gt;*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetTextOperationSaveValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value2"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Value3"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportToHtmlComment&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current set is intentionally compact. More text operations can be added in future versions based on developer feedback and practical use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regex-Based Element Selection
&lt;/h2&gt;

&lt;p&gt;The Criteria system can use regular expressions to select elements.&lt;/p&gt;

&lt;p&gt;Consider the following HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Regex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;2026-10-01&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Adrian&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;43&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;00125478744&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Brazil&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following commands select elements based on their text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Regex|*?t#\\d{4}-\\d{2}-\\d{2}$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"pink"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"Regex|*?t#^[0-9]+$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"brown"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;t&lt;/code&gt; criterion works with the text of the element, while &lt;code&gt;#&lt;/code&gt; specifies a regular-expression comparison.&lt;/p&gt;

&lt;p&gt;The first expression matches a date such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-10-01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second matches text consisting entirely of digits, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;43
00125478744
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The underlying WebFormsJS implementation uses JavaScript's &lt;code&gt;RegExp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tmpValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/([\s\S]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)\/([&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the Criteria system to perform more precise element selection without requiring a separate selector language.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Objects from WebForms
&lt;/h2&gt;

&lt;p&gt;A value beginning with &lt;code&gt;$&lt;/code&gt; in a WebForms class method can be interpreted by WebFormsJS as a JavaScript object reference.&lt;/p&gt;

&lt;p&gt;This provides a direct way for server-generated commands to refer to objects that exist in the browser.&lt;/p&gt;

&lt;p&gt;The distinction is important: the WebForms class generates the command, while WebFormsJS performs the corresponding client-side execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try and Catch
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 adds &lt;code&gt;Try&lt;/code&gt; and &lt;code&gt;Catch&lt;/code&gt; for explicit error handling.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Try&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;h5&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"div"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;h5&amp;gt;|&amp;lt;&amp;gt;-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"New tag!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New Tag Was Added!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Catch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h5 Tag Not Exist 1!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h5 Tag Not Exist 2!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an Action Control inside &lt;code&gt;Try&lt;/code&gt; encounters an error, execution stops and continues at &lt;code&gt;Catch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;Try&lt;/code&gt; and &lt;code&gt;Catch&lt;/code&gt;, there is no automatic recovery mechanism. The developer decides which operations may cause problems and places those operations inside an appropriate error-handling structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  LockQueue
&lt;/h2&gt;

&lt;p&gt;The queue behavior was changed in WebForms Core 2.2.&lt;/p&gt;

&lt;p&gt;In the previous version, the queue was automatically locked. In 2.2, the queue is no longer automatically locked in that way.&lt;/p&gt;

&lt;p&gt;The default duration is controlled by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;WebFormsOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QueueLockDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a process needs additional protection, the developer can explicitly call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LockQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;LockQueue&lt;/code&gt; dynamically increases the lock duration for the current process and then restores the previous configured value automatically.&lt;/p&gt;

&lt;p&gt;This is useful when a process must be allowed to complete before another queued process starts doing something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native HTML Validation from the Server
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 adds &lt;code&gt;SetCustomValidity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;WebForms Core does not introduce a new validation framework.&lt;/p&gt;

&lt;p&gt;Instead, it brings the browser's existing validation capability into the server-generated command model.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCommentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"(name)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;HtmlEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"custom-validity"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"custom-validity"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsEqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCustomValidity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"The username cannot be \"admin\"."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Else&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCustomValidity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser's native Constraint Validation API remains responsible for the validation behavior.&lt;/p&gt;

&lt;p&gt;The server determines the condition and sends the appropriate command to the HTML element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stable WebAssembly Support
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 brings stable WebAssembly support across seven languages and environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AssemblyScript&lt;/li&gt;
&lt;li&gt;C&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go and Rust provide WebAssembly targets directly, while AssemblyScript is designed specifically for WebAssembly.&lt;/p&gt;

&lt;p&gt;For example, Go can be built with its native WebAssembly target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;@echo &lt;span class="na"&gt;off&lt;/span&gt;

&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;js&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;wasm&lt;/span&gt;

&lt;span class="kd"&gt;go&lt;/span&gt; &lt;span class="kd"&gt;build&lt;/span&gt; &lt;span class="na"&gt;-o &lt;/span&gt;&lt;span class="kd"&gt;webforms&lt;/span&gt;&lt;span class="na"&gt;-go&lt;/span&gt;.wasm

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="na"&gt;/f &lt;/span&gt;&lt;span class="s2"&gt;"delims="&lt;/span&gt; &lt;span class="vm"&gt;%%i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'go env GOROOT'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;GOROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;%%i&lt;/span&gt;

&lt;span class="nb"&gt;copy&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%GOROOT%&lt;/span&gt;&lt;span class="s2"&gt;\lib\wasm\wasm_exec.js"&lt;/span&gt; &lt;span class="kd"&gt;wasm_exec&lt;/span&gt;.js

&lt;span class="nb"&gt;pause&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust can be built with the WebAssembly target and processed with wasm-bindgen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;cargo&lt;/span&gt; &lt;span class="na"&gt;+stable-x&lt;/span&gt;&lt;span class="m"&gt;86&lt;/span&gt;_64&lt;span class="na"&gt;-pc-windows-gnu &lt;/span&gt;&lt;span class="kd"&gt;build&lt;/span&gt; &lt;span class="na"&gt;--release --target &lt;/span&gt;&lt;span class="kd"&gt;wasm32&lt;/span&gt;&lt;span class="na"&gt;-unknown-unknown

&lt;/span&gt;&lt;span class="kd"&gt;wasm&lt;/span&gt;&lt;span class="na"&gt;-bindgen &lt;/span&gt;&lt;span class="kd"&gt;target&lt;/span&gt;&lt;span class="na"&gt;/wasm&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="na"&gt;-unknown-unknown/release/webformscore&lt;/span&gt;_wasm_test.wasm &lt;span class="na"&gt;--target &lt;/span&gt;&lt;span class="kd"&gt;web&lt;/span&gt; &lt;span class="na"&gt;--out-dir &lt;/span&gt;&lt;span class="kd"&gt;pkg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current implementations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AssemblyScript:&lt;/strong&gt; WebAssembly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C:&lt;/strong&gt; Emscripten&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C++:&lt;/strong&gt; Emscripten&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C#:&lt;/strong&gt; AOT and Runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go:&lt;/strong&gt; native WebAssembly support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java:&lt;/strong&gt; TeaVM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust:&lt;/strong&gt; native WebAssembly support and wasm-bindgen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;WebAssembly does not change the WebForms Core command model. It provides another execution environment while WebForms Core continues to generate WebForms responses and commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebForms Classes Across 18 Programming Languages
&lt;/h2&gt;

&lt;p&gt;WebForms Classes are now directly available for &lt;strong&gt;18 programming languages&lt;/strong&gt;, making WebForms Core accessible across a broad range of programming environments.&lt;/p&gt;

&lt;p&gt;The collection includes &lt;a href="https://www.npmjs.com/package/webformscore-wasm" rel="noopener noreferrer"&gt;&lt;strong&gt;AssemblyScript&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/webforms-core/Web_forms_classes/tree/elanat_framework/c" rel="noopener noreferrer"&gt;&lt;strong&gt;C&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/webforms-core/Web_forms_classes/tree/elanat_framework/cpp" rel="noopener noreferrer"&gt;&lt;strong&gt;C++&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.nuget.org/packages/WFC" rel="noopener noreferrer"&gt;&lt;strong&gt;C#&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://pub.dev/packages/webforms" rel="noopener noreferrer"&gt;&lt;strong&gt;Dart&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://hex.pm/packages/wfc" rel="noopener noreferrer"&gt;&lt;strong&gt;Elixir&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/webforms-core/go" rel="noopener noreferrer"&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://central.sonatype.com/artifact/net.elanat/WFC" rel="noopener noreferrer"&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/webformscore" rel="noopener noreferrer"&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/webforms-core/Web_forms_classes/tree/elanat_framework/julia" rel="noopener noreferrer"&gt;&lt;strong&gt;Julia&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://metacpan.org/dist/WFC" rel="noopener noreferrer"&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://packagist.org/packages/webforms-core/php" rel="noopener noreferrer"&gt;&lt;strong&gt;PHP&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://pypi.org/project/WFC/" rel="noopener noreferrer"&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://github.com/webforms-core/Web_forms_classes/tree/elanat_framework/r" rel="noopener noreferrer"&gt;&lt;strong&gt;R&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://rubygems.org/gems/wfc" rel="noopener noreferrer"&gt;&lt;strong&gt;Ruby&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://crates.io/crates/webformscore" rel="noopener noreferrer"&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://swiftpackageindex.com/webforms-core/swift" rel="noopener noreferrer"&gt;&lt;strong&gt;Swift&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://www.npmjs.com/package/webformscore-ts" rel="noopener noreferrer"&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WebForms Core 2.2 is currently available for &lt;strong&gt;.NET and Java&lt;/strong&gt;. The remaining language implementations will be updated to version 2.2 over the next &lt;strong&gt;10 days&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means the WebForms Classes ecosystem is not limited to a single backend language. Developers can use the same WebForms Core architecture and programming model across a wide range of languages and environments, while each implementation remains native to its own ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why WebForms Core Did Not Add Middleware
&lt;/h2&gt;

&lt;p&gt;One of the hardest architectural decisions during the development of 2.2 was whether to introduce a generic Middleware structure into WebForms Core.&lt;/p&gt;

&lt;p&gt;Technically, it was possible to build a very general Function-level Middleware system.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;B&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__middleware&lt;/span&gt; &lt;span class="o"&gt;??=&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newArgs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Such a system could do much more than a conventional Middleware implementation. It could change arguments, stop execution, and execute the original function again with new arguments.&lt;/p&gt;

&lt;p&gt;But there was a problem.&lt;/p&gt;

&lt;p&gt;Adding this abstraction to WebFormsJS would make the core considerably more complicated. Lifecycle management, recursion, execution order, argument changes, and the different paths through which Functions are executed would all have to be managed.&lt;/p&gt;

&lt;p&gt;In the end, we decided not to add it.&lt;/p&gt;

&lt;p&gt;Instead, when a requirement is genuinely specific to client-side processing, a &lt;strong&gt;JavaScript Module&lt;/strong&gt; is a better place for that logic.&lt;/p&gt;

&lt;p&gt;For example, if form data needs to be reduced or modified before submission, a JavaScript Module can perform that operation directly without adding a generic Middleware layer to WebFormsJS.&lt;/p&gt;

&lt;p&gt;This decision is not a statement that Middleware is impossible in WebForms Core.&lt;/p&gt;

&lt;p&gt;It is an architectural decision to keep the core smaller and move client-specific behavior into JavaScript Modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Changes
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 also includes several smaller improvements and fixes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflection renamed to Reflect
&lt;/h3&gt;

&lt;p&gt;The Reflection method has been renamed to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reflect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Debugger numbering
&lt;/h3&gt;

&lt;p&gt;Debugger logs now include numbering, making it easier to follow the execution sequence of generated Action Controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript Object escaping
&lt;/h3&gt;

&lt;p&gt;An escaping issue involving JavaScript Objects containing two consecutive &lt;code&gt;$&lt;/code&gt; characters was fixed.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebForms Core 2.1.1 and 2.1.2
&lt;/h3&gt;

&lt;p&gt;The 2.1.x maintenance releases also included several changes that lead into the 2.2 release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed the hash-link behavior so hash links no longer create an unnecessary server request.&lt;/li&gt;
&lt;li&gt;Added the Modulo Filter to Criteria.&lt;/li&gt;
&lt;li&gt;Fixed Replace behavior for values stored in Save and Cache.&lt;/li&gt;
&lt;li&gt;Added Fetch support in InputPlace.&lt;/li&gt;
&lt;li&gt;Removed CSharpMediator.&lt;/li&gt;
&lt;li&gt;CSharpWASM can infer the JavaScript file path from the WASM file path.&lt;/li&gt;
&lt;li&gt;CSharpWASM supports both CLI and AOT.&lt;/li&gt;
&lt;li&gt;Rust WASM can be built through wasm-bindgen or directly as WebAssembly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;WebForms Core 2.2 is not simply a collection of additional methods.&lt;/p&gt;

&lt;p&gt;The most important change is the introduction of higher-level operations that allow developers to describe what should happen to a UI without manually coordinating every underlying step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Render&lt;/strong&gt; is the clearest example.&lt;/p&gt;

&lt;p&gt;Snapshot, Rollback, and Transient DOM already provided the mechanisms needed to manage complex DOM transformations. Render combines those mechanisms into a single operation that can manage the transition from an existing UI state to a new one.&lt;/p&gt;

&lt;p&gt;At the same time, 2.2 keeps the underlying system explicit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fclbsr1eoo6mfxkuzg12z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fclbsr1eoo6mfxkuzg12z.jpg" alt="WebForms Core (WFC) 2.2" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Native browser validation remains native browser validation. Client-specific processing can remain in JavaScript Modules. WebAssembly provides additional execution environments without changing the WebForms Core command model. Queue locking is explicit when a process actually needs it.&lt;/p&gt;

&lt;p&gt;The result is a more capable WebForms Core without turning the core itself into a larger collection of abstractions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;On Elanat:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-core" rel="noopener noreferrer"&gt;Official WebForms Core Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elanat.net/webforms-js" rel="noopener noreferrer"&gt;Official WebFormsJS Page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core" rel="noopener noreferrer"&gt;WebForms Core Organizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsJS" rel="noopener noreferrer"&gt;WebFormsJS Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webforms-core/WebFormsClasses" rel="noopener noreferrer"&gt;WebForms Classes Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>opensource</category>
      <category>news</category>
      <category>webformscore</category>
    </item>
  </channel>
</rss>
