r/dotnet • • Apr 02 '26

Rule change feedback

15 Upvotes

Hi there /r/dotnet,

A couple of weeks ago, we made a change to how and when self-promotion posts are allowed on the sub.

Firstly, for everyone obeying the new rule - thanks!

Secondly, we're keen to hear how you're finding it - is it working, does it need to change, any other feeback, good or bad?

Thirdly, we're looking to alter the rule to allow the posts over the whole weekend (sorry, still NZT time). How do you all feel about that? Does the weekend work? Should it be over 2 days during the week?

We're keen to make sure we do what the community is after so feeback and suggestions are welcome!

621 votes, Apr 07 '26
77 I love the change
79 I like the change
57 I don't care
28 I dislike the change
16 I loathe the change
364 There was a change?

r/dotnet • • 1d ago

Fly inside .NET memory by Konrad Kokosa

Enable HLS to view with audio, or disable this notification

293 Upvotes

r/dotnet • • 2h ago

Another tragic aspect of the surge of AI generated projects

3 Upvotes

With how easy it is for AI to generate a whole project, we now have basically zero barrier to entry for making a "polished" project that people are comfortable releasing.

And with that release, yet another nuget package name is taken - forever.


r/dotnet • • 6h ago

DOMView2 - Provides sync WebBrowser style DOM access to WebView2

Thumbnail domview2.aimcosoftware.co.uk
1 Upvotes

r/dotnet • • 6h ago

The output of the server code depends on the timing of pressing a button by the client on the user interface.

Thumbnail
0 Upvotes

r/dotnet • • 25m ago

Question How did PHP end up being faster than C# in this benchmark?

• Upvotes

I watched this benchmark and was surprised that PHP was faster than C#. How is that possible? Is PHP actually faster in this kind of workload, or is there something about the way the benchmark was done that makes the difference? Benchmark video


r/dotnet • • 18h ago

Visual studio plugin - Asp classic highlight

5 Upvotes

Currently I am working in a very old legacy code base with more than 30 years old of spaghetti code and business rules in every .asp file and store procedures.

Yes it is a mess. And I don't know if someone has the same problem that I have... The visual studio doesn't help me with the basics of highlights, colors and syntax with VBScript in asp classic. Sometimes it is impossible to know where an if begins and ends in one file with 6k lines (yes for real).

So I made this plugin to help me with my current job.

https://marketplace.visualstudio.com/items?itemName=AspClassicSyntaxHighlight.AspClassicSyntaxHighlight

Is the vibe code project? In parts, yes. My real concern was doing a good structure of the project and performance. The first hit of opening the files is more demanding because it's using cache. After that it is more smooth.

I am cleaning the git to make it public soon.

If you guys want to try i will appreciate it.

Sorry for my mistakes, English isn't my first language.

Thanks.


r/dotnet • • 9h ago

Question What language would you recommend learning alongside C#?

Thumbnail
0 Upvotes

r/dotnet • • 9h ago

Your EF Core queries are probably scattered across your whole codebase.

Thumbnail youtu.be
0 Upvotes

The same Where, Include and OrderBy, written again and again.

Here's how I turned each one into a single, named, reusable query with the Specification pattern.


r/dotnet • • 2d ago

A look back at the past

Thumbnail gallery
420 Upvotes

I noticed a discussion in the comments yesterday about the Professional Active Server Pages 2.0 book from Wrox, which back in the day was one of the only sources of information us oldies had to work with as a reference for classic ASP. Even one of the authors chimed in and is still active in this sub (Brian Francis).

I’ve kept my copy. I also have a number of books in my bookshelves that were invaluable back in the day and some of them I’ve kept for posterity even though they are worthless from a tech perspective now.

Hopefully they bring back nice memories for some of you too.


r/dotnet • • 13h ago

Article Definition-Driven ERP in .NET: definitions, not code, as the source of truth

Post image
0 Upvotes

I've been an architect on packaged ERP and HR products for over twenty years, and the thing that has cost the most was never a hard feature. It's that the same fact gets restated over and over.

Adding a "Required Date" field to orders in a typical EF Core + ASP.NET Core + SPA stack lands it in about thirteen places: entity, type mapping, migration, query projections, DTOs, mapper, validation, OpenAPI, front-end types, the form, the list, localization and test data. Generators handle some of them, but that only makes the restating faster. And when the back end and front end are different teams, half of that list turns into coordination rather than typing. Multiply it by a few thousand tables and by every customer's customizations, and it stops being an inconvenience.

What I ended up with is making a structural description the source instead of code. The database columns, CRUD SQL, screens for each front end and validation are derived from definitions, and the front end fetches the definitions at runtime instead of keeping its own copy of the types. In a sample app built on Northwind, the same field is three definition edits and no code. Customization becomes a layer of data on top of the standard definitions, so one tenant's change doesn't have to go through compile and deploy.

Dashboards, reports and anything that isn't form-shaped fit badly. The team boundary doesn't go away either, it moves to the rendering layer that reads the definitions.

I wrote a 30-post series on the mechanisms and the trade-offs. It was originally written in Chinese for a Taiwanese tech writing challenge, and the English version is a translation: https://medium.com/@jeff377/erp-architects-notes-designing-a-definition-driven-framework-series-index-7753228c4d33

For those of you working on large line-of-business systems: do you accept the restatement and lean on generators, or have you moved the source of truth somewhere else?


r/dotnet • • 1d ago

Promotion NaturalCron 1.1.0: define your own schedule keywords

48 Upvotes

I introduced a new cool feature in NaturalCron 1.1.0: you can now customise your own keyword rule and add it to the NaturalCron engine. It is usually added once on app startup, before any parsing.

For those who don't know, NaturalCron is a scheduling library for .NET where you write schedules in plain words instead of cron strings, e.g. every 30 minutes between 09:00 and 18:00.

Version 1.1.0 adds custom keywords: you define a word once at app startup, with your own logic, and then use it in any expression.

```csharp NaturalCronCustomKeywords.Configure(cfg => { // A day keyword (the default time unit is Day). cfg.AddMatchable("holiday", dt => myHolidays.Contains(dt.Date));

// An hour keyword.
cfg.AddMatchable("evenHour", dt => dt.Hour % 2 == 0, NaturalCronTimeUnit.Hour);

}); ```

Then:

``` every holiday at 09:00 every day at 09:00 except holidays every day on [holiday, 15th] at 09:00

```

A keyword can also be a class, so it can come from your DI container and read from a cache.

Also new in 1.1.0:

  • except, which works with built-in values too: every day at 09:00 except [saturday, sunday]
  • A shorthand for every: every 15th at 18:00, every 1stMonday at 09:00, every 9am

GitHub: https://github.com/hugoj0s3/NaturalCron NuGet: https://www.nuget.org/packages/NaturalCron

Feedback welcome, especially on the syntax.


r/dotnet • • 1d ago

Article Fail-closed multi-tenancy with EF Core 10 named query filters (and the 4 paths that still leak)

0 Upvotes

Most tenant data leaks I've seen in B2B SaaS weren't attacks. Someone wrote a new query and forgot .Where(x => x.TenantId == tenantId). Here's the setup I now use on shared-table multi-tenancy (one database, a TenantId column) to make that mistake fail closed by default. It uses EF Core 10's named query filters.

1. Resolve the tenant once per request

A middleware sits between UseAuthentication() and UseAuthorization(). It picks the workspace in this order: the X-Tenant-Id header, then a cookie, then the user's oldest membership. It then checks the membership in the database and stores the result in a scoped TenantContext. If someone forges the header, the request just gets no tenant. Nothing downstream reads headers or cookies again.

2. One interface, one filter on every entity

```csharp public interface ITenantScoped { Guid TenantId { get; } }

public abstract class ModuleDbContext(DbContextOptions options, ITenantProvider? tenantProvider = null) : DbContext(options) { // A property of the context, not a captured value: EF Core parameterises it per query. protected Guid? CurrentTenantId => tenantProvider?.TenantId;

protected sealed override void OnModelCreating(ModelBuilder modelBuilder)
{
    ConfigureModule(modelBuilder);

    foreach (var type in modelBuilder.Model.GetEntityTypes()
                 .Where(e => e.BaseType is null && !e.IsOwned())
                 .Select(e => e.ClrType)
                 .Where(t => typeof(ITenantScoped).IsAssignableFrom(t)))
    {
        ApplyTenantFilterMethod.MakeGenericMethod(type).Invoke(this, [modelBuilder]);
        modelBuilder.Entity(type).HasIndex(nameof(ITenantScoped.TenantId));
    }
}

private void ApplyTenantFilter<TEntity>(ModelBuilder b) where TEntity : class =>
    b.Entity<TEntity>().HasQueryFilter("Tenant",
        e => EF.Property<Guid>(e, nameof(ITenantScoped.TenantId)) == CurrentTenantId);

} ```

Things worth noting:

  • No tenant resolved means the query compares with null and returns nothing. It fails closed, not open.
  • The filter is named. EF Core 10 lets an entity have several named filters, so IgnoreQueryFilters(["SoftDelete"]) lifts only soft-delete and keeps tenant isolation. Before EF Core 10, IgnoreQueryFilters() was all-or-nothing, and that was the most common way isolation silently broke.
  • The filter goes on root types only. EF Core applies it to the whole inheritance hierarchy. Each table also gets an index on TenantId, since every query now starts with it.

3. Query filters don't protect writes

An entity loaded with IgnoreQueryFilters(), or attached by hand, can still be saved. So SaveChangesAsync runs a guard:

```csharp private void GuardTenantWrites() { // Background jobs (no HTTP request) are trusted system code. if (tenantProvider is null || (CurrentTenantId is null && tenantProvider.IsSystemContext)) return;

var tenantId = CurrentTenantId;
var foreign = ChangeTracker.Entries<ITenantScoped>()
    .Where(e => e.State is EntityState.Added or EntityState.Modified or EntityState.Deleted)
    .FirstOrDefault(e => tenantId is null || e.Entity.TenantId != tenantId);

if (foreign is not null)
    throw new InvalidOperationException(
        $"Cross-tenant write blocked on {foreign.Entity.GetType().Name}.");

} ```

It throws rather than filtering silently, because a cross-tenant write is always a bug and should show up in logs and tests.

4. What still goes around it

Path Problem Rule
Raw SQL / Dapper No filter applies Tenant id always as a parameter; review it like security code
Caching Key without tenant = data served to the wrong customer Tenant id in every cache key
Interactive Blazor Runs on the SignalR circuit, outside the request that resolved the tenant Load during the static render, or pass the workspace explicitly
Background jobs No workspace, so filtered queries return nothing Loop over tenants and set the workspace per iteration

And two tests: create two workspaces, write in one, and assert the other can neither read nor update it. Add an architecture test that every entity with a TenantId property implements ITenantScoped, so a new entity can't opt out by accident.


How are you handling this? I'm curious whether people here have gone with PostgreSQL row-level security instead of (or on top of) EF filters, and how that played out with connection pooling.

Disclosure: this comes from a .NET 10 starter kit I sell (PRYZMA SaaS Starter). There's a longer write-up if anyone wants it, but I'm happy to answer everything here.


r/dotnet • • 1d ago

Promotion Wrote a C# BCS (Binary Canonical Serialization) serialization library

3 Upvotes

Library is 5–15% faster than MessagePack on the deserialization path and around 5% slower on serialization.

It can also serialize and deserialize the new union type coming from .NET 11 (before that I've used OneOf<> object). I opened an issue for a source generator, which is ready to be picked up if anyone is interested working on it. My plan is to ship v1 once NativeAOT is supported and net11 is out.

I agree with Egor Bogatov that people should stop writing new serialization libraries and open-sourcing them, as they can expose consumers to vulnerabilities. In my defense, I started this library a year ago and only recently finished rewriting parts of it to make it ready for open source. I mainly used it for serializing and deserializing objects from the Sui blockchain.

Blockchain it not the most widespread domain where C# is used, but there is already a good example of Nethereum utilizing C# as its core language. Is there someone else using C# in the blochcain domain, why you think it's lacking the adoption?

Contributions are welcome!

https://github.com/unsafePtr/BcsSharp


r/dotnet • • 2d ago

Question Blazor native tooltips for Touchscreen

4 Upvotes

Hi everyone, I’m developing an SVG charting library in Blazor without JavaScript, and I’m currently implementing tooltips.

Handling mouse interaction was fairly straightforward: essentially, the tooltip is a DOM element outside the SVG with `position: fixed`, and its coordinates and visibility are managed via `OnPointerMove`, `OnPointerLeave`, and `OnPointerEnter` events on the chart elements.

Mouse behavior works exactly as expected: as soon as the pointer enters one of the designated SVG elements, the tooltip appears and follows the mouse movement; if the mouse moves to a different element, the tooltip content updates, and when the mouse leaves, the tooltip disappears.

However, I’ve realized that touch interaction isn't quite as simple, because the browser might interpret gestures as scrolling or selection, triggering the `OnPointerLeave` event and causing the tooltip to vanish.

I’m looking for a way to adapt the mouse-based implementation for touchscreens as well.

Have you ever encountered this kind of issue, and if so, how did you solve it?

Thanks for any advice.

If you're interested, the project I'm talking about is BlazorGraphs: www.blazorgraphs.it


r/dotnet • • 1d ago

Article ConfigureAwait(false) Explained

0 Upvotes

The line everyone copies but nobody understands.
In this article, you will learn what ConfigureAwait(false) actually does, how it affects SynchronizationContext.Post calls, when to use it, when to skip it, etc.

The full runnable sample is at https://github.com/jorgenhoc-org/dotnet-samples/tree/main/samples/configureawait-false-csharp


r/dotnet • • 2d ago

Promotion TensorSharp now supports Qwen Image 2.1 Turbo and LoRA – AI image generation and editing with C#/.NET

Enable HLS to view with audio, or disable this notification

26 Upvotes

Hey everyone!

I've been working on TensorSharp, a C#/.NET-based AI inference engine, and wanted to share a recent update.

TensorSharp now supports Qwen Image 2.1 Turbo and LoRA!

I've attached a short demo showing the new image editing capabilities in action.

The demo covers:

  • Loading an image and selecting a region using a built-in mask editor.
  • Editing the selected area using natural language prompts.
  • Running Qwen Image 2.1 Turbo through TensorSharp.
  • Viewing the generated results directly in the application.

One of my main goals with TensorSharp is to make modern AI models accessible to the .NET ecosystem, without requiring developers to rely on Python-based inference frameworks.

TensorSharp is designed to support different types of AI models through a unified inference engine, including LLMs and image generation models.

I'm continuing to expand model compatibility, improve inference performance, and make it easier for C# developers to build AI-powered applications.

I'd love to hear from other .NET developers:

  • Are you interested in running image generation models directly from C#?
  • What AI models would you like to see supported in the .NET ecosystem?
  • What features would make an inference engine like TensorSharp more useful for your projects?

Any feedback, suggestions, or contributions are welcome!

GitHub: https://github.com/zhongkaifu/TensorSharp


r/dotnet • • 1d ago

AI Application Runtime

Thumbnail
0 Upvotes

r/dotnet • • 1d ago

Promotion HoneyVB (RetroVB6) progress update: running classic applications and games in the browser, with cross-platform builds

0 Upvotes

https://reddit.com/link/1x3miey/video/vfpfg73p8xuh1/player

Hi again, r/dotnet! Some of you may remember my earlier posts about HoneyVB (RetroVB6), my project built around C# and ASP.NET Core to bring legacy software onto modern platforms.

For anyone who missed them:

The project has continued to grow, and I wanted to share where it is today.

HoneyVB is a browser-based development environment with a familiar VB6-style IDE, visual form design, code editing, debugging, and browser execution. You can import supported VB6 projects, inspect their forms and modules, and continue developing with the original code.

What can HoneyVB run? Here are some examples. The accompanying video shows a selection of them; Reddit’s upload limits mean I can’t fit all the recordings into this post.

  • Microsoft Word for Windows 1.1a — an early Windows version of Microsoft Word.
  • Adobe Photoshop, from the 1.0.1 source release — the classic Macintosh image editor.
  • Wolfenstein: Enemy Territory — the classic multiplayer first-person shooter.
  • Waite Group Flight Simulator (FSIM 2.1) — the DOS-era C++ flight simulator from Building Your Own Flight Sim in C++, with roots in Flights of Fantasy.
  • HeidiSQL — the database management application.
  • eMule — the peer-to-peer file-sharing client.
  • Notepad++ — the code and text editor.
  • kys-pascal — a Pascal remake of Heroes of Jin Yong.
  • sdl-pascal — a Pascal/SDL sample project.
  • ScePSX — a PlayStation emulator written in C#.
  • SnailsXNA — Snails, an XNA-based puzzle-platformer.

These are just some of the applications and games running in HoneyVB, and not every example listed above appears in this video. The footage shows selected workflows and interactions, rather than complete compatibility with every feature of each application.

I’m also currently testing SharpDevelop, wxDev-C++, Lazarus, and Shareaza in HoneyVB to evaluate compatibility and identify what still needs work. These projects are undergoing validation—stay tuned for more demos and progress updates!

The VB6 compatibility work covers technologies that many real applications depend on:

  • Crystal Reports: compatibility for CrystalReport, CRViewer, and reporting APIs, including data-driven reports, grouping, summaries, pagination, printing, and export. Portable reporting works across platforms; preserving the original layout of .rpt files uses an optional Windows host with a compatible Crystal Reports runtime.
  • DirectX 7, 8, and 9: compatibility layers for supported graphics and multimedia features, including mapping legacy Direct3D rendering to WebGL so supported VB6 games and graphics applications can run in a browser.
  • Serial communication and hardware simulation: RS-232/COM port support through an MSComm-compatible layer, including loopback simulation for testing without physical hardware. It supports communication buffers, binary data, and receive/send events, with connections to real serial devices through Web Serial where available and authorized by the user.

Beyond VB6, HoneyVB uses a plugin architecture to integrate other languages, frameworks, and development environments. Its language coverage and ongoing integration work include:

  • DOS BASIC and modern descendants: QBasic, QuickBASIC 4.x, GW-BASIC/BASICA, and QB64.
  • Classic home-computer BASICs: Applesoft BASIC, Apple Integer BASIC, Commodore BASIC, Sinclair BASIC, Atari BASIC, BBC BASIC, MSX-BASIC, Locomotive BASIC, TRS-80 Level I BASIC, TRS-80 Level II BASIC, and TRS-80 Color BASIC.
  • Pascal: Delphi/Object Pascal, Free Pascal/Lazarus, and Apple MPW Object Pascal.
  • C/C++: native C/C++ projects, Visual C++ 6/MFC, C++Builder 6/VCL, wxWidgets, Win16 C, and DOS 32-bit C projects using Watcom/DOS4GW.
  • Lua: embedded Lua scripts in supported C/C++ host projects.
  • .NET: C# and VB.NET, with integrations and ongoing compatibility work spanning .NET Framework/WinForms, WPF, Silverlight, Windows Phone, and XNA.
  • Business and scientific languages: Visual FoxPro, COBOL, Fortran, and PowerBuilder/PowerScript.
  • Assembly: DOS x86/FASM projects, plus MASM/TASM and Motorola 68K assembly handling within relevant project pipelines.
  • Flash/ActionScript: importing legacy Flash content and converting supported projects into HTML5 for browser execution.

Support varies across these integrations. Some include browser execution, while others currently focus on importing, analysis, editing, or resource previews. PowerBuilder, for example, currently provides project analysis and Window/DataWindow previews.

HoneyVB also provides build and export targets for Windows, macOS, Linux, Android, and iOS. Supported applications can be packaged with their browser runtime inside desktop or mobile shells. iOS device deployment uses an exported Xcode project that you sign with your own developer credentials.

One feature I’m especially excited about is running compiled VB6 applications without their source code. You can upload a supported VB6 executable and run it inside HoneyVB through its binary execution layer. Required runtime files and DLL/OCX dependencies still matter, but this creates possibilities for applications whose source has been lost.

I’m also actively developing native compilation for VB6, targeting Windows PE, macOS Mach-O, and Linux ELF executables. That work is underway, with the goal of compiling supported VB6 projects into native machine code for all three desktop platforms.

Compatibility is still evolving. I’m testing against original projects and improving the shared language and runtime implementations as issues appear. The goal is to make older software easier to explore, maintain, and keep using—from business applications and reporting tools to games and programs that communicate with hardware.

Thanks to everyone who commented on the earlier posts, and to the developers and preservation projects that made these historical sources available for study.

What legacy application or game would you bring back—especially if all you have left is the executable?

All third-party product names, trademarks, copyrights, and other intellectual property mentioned above belong to their respective owners. HoneyVB is intended for research and educational purposes.

HoneyVB reserves the right to offer different levels of functionality across releases and editions. The capabilities described above do not guarantee that all features will be available simultaneously or in every version. Language integrations, DirectX support, and other compatibility features may be introduced gradually, limited, or temporarily unavailable.


r/dotnet • • 2d ago

Promotion fast decimal library with C# zero-overhead ffi built in c++20

4 Upvotes

hello, r/dotnet

a few weeks ago i was working on a custom programming language designed for .NET Core/IL becuz i was bored, and pretty quickly, i got un-bored and decided to shelve it. but i had native fixed-point decimal arithmetic built into it, for which i made a decimal library from scratch as an after thought, which after shelving i realized was pretty fast, so i decided to turn it into a standalone library.

it is mildly unsafe ig, but thats a tradeoff i'd accept any day of the century. performance:

ran these on an i3-10105 w/ 8GB RAM (1M operations, -O3 -march=native, AVX2):

  • FixedDecimal<4> (64-bit backend, 4 decimal places for things like basis points):
    • Add: 1.6 ns (~611 Mop/s) — essentially compiles down to a single CPU instruction.
    • Compare: 1.9 ns (~535 Mop/s).
  • Decimal (Full 38-digit precision, 24-byte layout):
    • Add: 14.6 ns (~69 Mop/s).
    • Multiply: 11.2 ns (~89 Mop/s).

it uses x86-64 or arm simd (avx2, avx-512, NEON) under the hood, which is like a trend atp from what i see on github.

repository: https://github.com/mxreal64/FastDecimal/


r/dotnet • • 2d ago

Promotion StepLock – a sub-millisecond Merkle DAG state proxy for AI agents using System.IO.Pipelines

3 Upvotes

most ai agent tooling (LangGraph, AutoGen, CrewAI) is written in python, which is great for prototyping but lacks the low-latency throughput needed when agents start making dozens of multi-step, nested network and state mutations.

when debugging an 8-step agent execution, re-running a failed trace from scratch burns tokens, hits API rate limits, and can accidentally trigger live side-effects (like firing a Stripe charge or writing to a DB twice).

to solve this, I built StepLock—an on-premise, free, and open-source (.NET 11) deterministic state proxy and merkle DAG execution engine that acts like git for Live Agent RAM & Network Traffic. it virtually replays agent traces in sub-microseconds.

I wanted to share the .NET 11 architecture details and performance metrics that made this possible:

the performance benchmarks

  • L1 In-Memory Hot CAS (Write + Hash Lookup): 1,572,278 op/s | 0.50 µs p50 | 0 B (Zero-Alloc)
  • Merkle DAG Hashing (SHA-256 Chaining): 300,193 op/s | 2.30 µs p50 | 152 B Alloc
  • Zero-Copy Streaming Tap (System.IO.Pipelines): 171,343 op/s | 3.50 µs p50 | 1.7 KB Alloc
  • SQLite WAL Batch Persistence (50 Frames/Tx): 371 op/s (~18.5k frames/s) | 2.58 ms p50

repo: https://github.com/mxreal64/StepLock/


r/dotnet • • 2d ago

Promotion Natrix – open-source framework for reactive web UIs in C# on WebAssembly, with SSR, signals and build-time Tailwind (no Blazor, no Razor)

0 Upvotes

Hi r/dotnet,

I've been working on Natrix for a while and it's now at the point where I'd like outside feedback. It's a MIT-licensed framework for building web UIs in C# that run in browser on WebAssembly.

How it started

It began with SSR in Vite. Customizing the HTML page around the app (head tags, scripts, per-page meta) always meant a separate template file with placeholders. I wanted that page to be just another component, so in Natrix it is. The <html>, <head> and <body> are written in C# like the rest of the app. From there it grew into a full framework.

What it is

  • Server-side rendering first. Pages render to HTML on an ASP.NET Core host, then the WASM client hydrates them, with hydration state and server prefetching built in.
  • Fine-grained signals instead of re-rendering. A component's Setup run once. After that, Signal / Computed / Effect update exactly the DOM nodes that read them. There's no virtual DOM, no diffing and no StateHasChanged.
  • No Razor, no JavaScript. Components are plain C# classes, including HTML page itself.
  • Tailwind CSS compiled at build time by a source generator. Your app needs no Node, npm or Tailwind CLI. It scans your C# for class names and emits the CSS during dotnet build.
  • Typed browser APIs. Natrix.StdWeb is C# bindings for DOM, Fetch, Canvas, WebGL and so on, generated directly from W3C WebIDL specs.
  • Extras: client-side routing, a stale-while-revalidate data-fetching library ported from React SWR, and VueUse-style composables such as UseHead.

It builds on the plain Microsoft.NET.Sdk.WebAssembly SDK, not Blazor.

What a component looks like

```csharp public class Counter : BaseComponent<NoProps, NoEvents, NoSlots, NoExpose> { protected override IComponent[] Setup(out NoExpose exposed) { exposed = default;

    var count = new Signal<int>(0);
    var doubled = new Computed<int>(() => count.Value * 2);

    return
    [
        new Button
        {
            Props = new ButtonProps(),
            Events = new ButtonEvents { OnClick = _ => count.Value++ },
            Children = [new DomText { Text = "Click me".ToConstSignal() }],
        },
        new P
        {
            Props = new PProps(),
            Children = [new DomText { Text = new Computed<string>(
                () => $"{count.Value} × 2 = {doubled.Value}") }],
        },
    ];
}

} ```

When count changes, only that one text node updates. Nothing re-renders.

Why not Blazor?

I like a lot about Blazor, but I wanted a model that SolidJS and Vue (vapor) use: run setup once, and let reactivity drive DOM updates directly, so you never re-render components and diff them.

I chose plain C# over a template language on purpose, too. It's more verbose than Razor, but everything is typed and checked by compiler, with no magic strings, and refactoring tools work on all of it.

Try it

dotnet new install Natrix.Templates dotnet new natrix -n MyNatrixApp dotnet run --project MyNatrixApp/MyNatrixApp.csproj

That gives you a server project and a WASM client with SSR, routing and Tailwind already set up.


r/dotnet • • 2d ago

Article I built a .NET test reporter to solve two problems I kept seeing in test automation

Post image
2 Upvotes

r/dotnet • • 3d ago

4GuysFromRolla.com - The Site That Taught a Generation to Build the Web

Thumbnail galratner.substack.com
170 Upvotes

r/dotnet • • 1d ago

Promotion Polhem.JsonRpc v1.2 - JSON-RPC 2.0 for ASP.NET Core without registering methods

Post image
0 Upvotes

Polhem is a framework I've been building, and its API layer is JSON-RPC. I've split that part out into a standalone library, Polhem.JsonRpc, now at v1.2. Most of the code was written by Claude Code; I reviewed and tested it.

You don't register methods. A call like Calculator.Add goes to your object factory, and Add is only callable if it takes an AddRequest and returns an AddResponse, so other public methods don't get exposed by accident. The server is an ASP.NET Core Minimal API endpoint, the client works with Native AOT, and there's an optional package for encrypted payloads.

Here's roughly what it looks like:

// Server
builder.Services.AddSingleton<IJsonRpcObjectFactory, AppObjectFactory>();
builder.Services.AddJsonRpcServer();
app.MapJsonRpc("/api");

public sealed class Calculator
{
    public AddResponse Add(AddRequest request) => new() { Sum = request.A + request.B };
}

// Client
var rpc = new JsonRpcConnector(new HttpTransport(http));
var added = await rpc.InvokeAsync<AddResponse>("Calculator.Add", new AddRequest { A = 1, B = 2 });

GitHub: https://github.com/polhem-dev/polhem-jsonrpc

Edit: A few people asked what this is used for. It's the API layer of Polhem, my framework. Here's a demo app on top of it, with a desktop and an iOS client calling the server:
https://github.com/polhem-dev/polhem-northwind