RSSAmplifier

Sebastian Gingter · Jul 6, 2026

.NET News June 2026

0
Sign in to vote or save

gingter.org

Last month I closed with the observation that Build 2026 was kicking off and that this edition would be a very different kind of busy. I was right, but not in the way I expected. The Build headlines were about AI (of course they were), but the thing I will remember June 2026 for is much older than any agent framework: C# finally has union types you can compile. People have been asking for discriminated unions for well over a decade. In June, union became a keyword you can actually type into a real preview SDK and have the compiler check your switch expressions for exhaustiveness.

Beyond that: Build gave us a proper look at dotnetup (the rustup-style installer story .NET should have had years ago), .NET 11 Preview 5 landed on Patch Tuesday together with a three-CVE servicing release, EF Core grew an analyzer that calls out one of my favorite pet peeves, Visual Studio 18.7 arrived with the Copilot cost visibility everyone suddenly needs, and the Critter Stack crew apparently does not believe in summer breaks.

Let me walk through it.

Build 2026: two days, a lot of AI, and a few things with substance

Build happened on June 2 and 3 at the Fort Mason Center in San Francisco, in a new, smaller format: two days, hands-on sessions, keynotes streamed for free. The messaging was exactly what you would expect in 2026. .NET 11 is “built for the AI era”, agents everywhere, Copilot deeper in debugging, profiling, and testing, AI-assisted merge conflict resolution, the whole program.

I have learned to apply a simple filter to Build announcements: ignore the adjectives, look for the things you will still be using in two years. This year, three items passed that filter for me.

Union types got the big stage. The C# session at Build was essentially the public coming-out for the feature, and I appreciated that Microsoft framed it correctly: unions are not an AI feature, they are a modeling feature. Closed sets of data shapes (wire protocols, domain states, results that are either a success or one of a known list of failures) are exactly the thing C# has forced us to fake with class hierarchies and discipline. More on the concrete state of the feature in the Preview 5 section below, because that is where it stopped being slideware.

dotnetup is the sleeper hit. A new cross-platform tool to install and manage .NET SDKs and runtimes, doing for .NET what rustup does for Rust and nvm does for Node: user-scoped installs without elevation, reading your global.json and fetching the right SDK for the repo automatically, a manifest of what is installed so updates are auditable, multiple runtimes side by side. If you have ever onboarded a new team member and watched them fight three different SDK installation methods (installer, script, package manager, each leaving slightly different state behind), you know why this matters. It is still in internal preview with a public preview announced for the coming months, and the stated goal is for it to become the official way to install .NET. Good. It is about time this stopped being a choose-your-own-adventure.

Modernization became a product instead of a slide. Web Forms to Blazor migration paths, agentic tooling that analyzes large codebases and plans upgrades, and Managed Instance on Azure App Service for running legacy apps without a rewrite. I am professionally obligated to be skeptical about “AI modernizes your legacy app” claims (I have seen too many legacy apps), but the direction is right: the hard part of modernization was never writing new code, it was understanding the old code, and that is a job where machine assistance genuinely helps.

The rest of the .NET content at Build (AI building blocks, agentic web development with ASP.NET Core and Aspire, on-device AI with MAUI, and the Agent Framework picking up multi-agent handoff orchestration with explicit topology and guardrails) is worth a look if you work in those areas; the session playlist is linked in the sources. The honest caveat applies as every year: Build is where the direction gets set, not where everything ships.

.NET 11 Preview 5: the month union became real

Preview 5 shipped on June 9, and the headline writes itself: union declarations and union patterns are in. The runtime side (UnionAttribute and the IUnion interface) landed in this preview too, which means the feature now exists end to end, from language syntax down to the plumbing.

The shape of it is pleasantly boring:

public union Pet(Cat, Dog, Bird);

That declares a closed type that holds exactly one of Cat, Dog, or Bird. Values convert implicitly (Pet pet = new Dog("Rex"); just works), and the part that actually changes your day-to-day: the compiler checks switch expressions over a union for exhaustiveness. Cover all case types and you do not need a discard arm. Add a fourth case type next year and every switch in your codebase that does not handle it turns into a compiler diagnostic instead of a 3 a.m. production incident. That is the whole point of discriminated unions, and it is why the workarounds (OneOf, hand-rolled class hierarchies, source-generated unions) never quite got there: they could give you the data shape, but not the compiler guarantee across your whole codebase.

Two honest caveats. First, it is a preview of a preview: parts of the proposal are explicitly not implemented yet (most notably union member providers, so you cannot access shared members across case types without pattern matching first). Second, nullability does what nullability always does: if any case type is nullable, your switch needs a null arm before the compiler calls it exhaustive. Fair enough. Alongside unions, closed class hierarchies landed as the underlying building block, giving you exhaustiveness over your own hand-built hierarchies too.

The rest of Preview 5 is a solid grab bag:

  • System.Text.Json learned JSON Lines (newline-delimited JSON). If you have ever streamed log records or fed an LLM batch API, you have hand-rolled this exact loop. Now it is in the box.
  • LINQ got full outer joins, completing the join story that LeftJoin and RightJoin started in .NET 10.
  • X25519 key agreement joined the cryptography stack, and Random picked up generic numeric APIs.
  • On the runtime side, runtime-async shed another piece of its preview scaffolding: a net11.0 project no longer needs <EnablePreviewFeatures> to opt in, just <Features>runtime-async=on</Features>, and suspension handling got faster on top. This has been the quiet long-running story of the whole .NET 11 cycle, and after last month’s “the BCL itself is compiled with it”, dropping the preview gate is the next logical step toward on-by-default.
  • File-based apps can now reference other C# files. The single-file dotnet run app.cs story keeps growing up: what started as “run a snippet” is turning into a legitimate lightweight project model, one carefully chosen capability at a time.
  • The SDK build can now run vulnerability and end-of-life checks as part of the build itself. Supply chain hygiene moving from “extra tool you should run” to “the build tells you” is the right direction.

MAUI got a reliability-focused wave: animations gained CancellationToken-aware overloads, the Windows Maps control got a real implementation backed by Azure Maps, and .NET for Android stabilized API 37 support.

The one that will start arguments: .NET 11 raises the hardware floor

Tucked into the Preview 5 cycle is a breaking change that deserves more attention than it got: .NET 11 raises the minimum hardware requirements. On x64, the baseline moves from x86-64-v1 to x86-64-v2 (so SSE4.2, POPCNT, and friends are now assumed), and the ReadyToRun images in the shipped runtime even target x86-64-v3 on Windows and Linux. On Windows Arm64, the LSE atomics instruction set is now required; Linux Arm64 stays where it was, so your Raspberry Pi is safe.

My take: right call. The v2 baseline covers every CPU that Windows 10 and 11 officially support, and the last chips below it left support around 2013. Carrying fallback code paths for twelve-year-old hardware taxes the JIT and everyone running modern silicon, which is nearly everybody. But “nearly” is doing work in that sentence: if you deploy .NET to older embedded boxes, industrial hardware, or that one ancient VM host nobody talks about, .NET 11 is the release where you check the CPU baseline before you plan the upgrade, not after the first crash report. That is not usually a step in a .NET major upgrade. This year it is.

ASP.NET Core and Blazor

The web stack items in Preview 5 are small but well aimed.

Blazor static server-side rendering now supports client-side validation. SSR has been the pragmatic middle ground of the Blazor story (no circuit, no WebAssembly download, just fast HTML), and missing client-side validation was one of the gaps that kept pushing people to interactive render modes they did not otherwise need. One less reason.

In the same spirit, QuickGrid now works without interactivity, and SupplyParameterFromSession joins last month’s SupplyParameterFromTempData in the family of “flow state through the framework instead of hand-rolling plumbing” attributes. There is also a new Blazor WebAssembly Gateway component; if you run WebAssembly apps behind a backend, that one is worth a look.

EF Core 11 Preview 5: the analyzer I have been waiting for

EF Core’s Preview 5 list looks modest until you find the item that pays for the whole release: EF1004, a new diagnostic that fires when an async EF query is executed synchronously.

You know the pattern. Someone calls .Result or .GetAwaiter().GetResult() on a query, it works fine on their machine, and then the app deadlocks or starves the thread pool under production load. I have written before that there is no reason not to await a Task (really, there isn’t), and I have spent enough hours in other people’s codebases digging out exactly this bug to be genuinely happy that the tooling now yells before it becomes a production problem. Turn the warning into an error in your build. You will thank yourself.

The rest:

  • Full outer joins work on Queryable, so the new LINQ operator translates to SQL.
  • The SQL Server provider now defaults to compatibility level 160 (SQL Server 2022). A sensible new default, but check it if you are still on an older server.
  • EnsureCreated and Migrate (and their async versions) now use an execution strategy, so transient failures during migration get retried instead of failing your deployment because the database blinked.
  • dotnet ef works against file-based apps, so migrations and scaffolding are available in the single-file model too.
  • Query translation got another cleanup pass: fewer pointless subqueries, no more no-op CASTs around value-converted columns. Every release, the generated SQL looks a little less like it was written by a machine that hates DBAs.

The June servicing release: three CVEs, one Blazor Server angle

Patch Tuesday (June 9) brought .NET 10.0.9, 9.0.17, and 8.0.28, closing three CVEs:

  • CVE-2026-45591 — Denial of service in ASP.NET Core (.NET 8/9/10), CVSS 7.5. This is the one to read: it sits in the MessagePack hub protocol used by SignalR and Blazor Server. Deeply nested MessagePack arrays can trigger a stack overflow and take your process down. If you run Blazor Server or SignalR with the MessagePack protocol exposed to the internet, patch this one first.
  • CVE-2026-45490 — Elevation of privilege in the .NET SDK, CVSS 7.8.
  • CVE-2026-45491 — Tampering in .NET 8/9/10, CVSS 6.2.

No .NET Framework updates this month, which is the good kind of boring.

And since I promised last month I would keep saying it: if any of your production apps ran ASP.NET Core data protection on .NET 10.0.0 through 10.0.6 back in April, patching was only half the job. If you have not rotated your data protection key ring yet, previously forged tokens are still valid. Rotate the keys.

Visual Studio 2026 18.7: seeing the Copilot bill before it hurts

The June update for Visual Studio 2026 (18.7.0 on June 9, with servicing releases through 18.7.3 on June 30) has a clear theme: visibility and trust.

The centrepiece is the reworked Copilot usage window. Since June 1, GitHub bills Copilot by token consumption instead of by request, and Visual Studio now shows that consumption in near real time, with proactive alerts when you approach your limit, hit it, or slide into overage billing. I did a full Kassensturz on what the token-based billing actually costs in practice in a recent German article, and the short version is: the difference between a fixed subscription and a metered one is not the invoice, it is that you start rationing your own tool usage. A live meter in the IDE does not fix that psychology, but flying blind was strictly worse. If you use Copilot in agent mode at all, open that window once and look at what a single afternoon costs you. It is educational.

The second theme is MCP server trust. Visual Studio now fingerprints an MCP server’s configuration and assets against a trusted baseline at startup; if anything changed, you get a trust dialog before the server runs. Given that MCP servers are executable code with access to your context, and given how casually people install them, this is a necessary layer, and I expect every editor to grow an equivalent. (The Swiss cheese model applies to your IDE too.)

Also in the update: long-distance next edit suggestions (Copilot can now propose the follow-up edit anywhere in the file, not just around your cursor), pull request review and approval inside the IDE for GitHub and Azure DevOps including inline comments, the C++ modernization agent reached general availability for MSVC toolset upgrades, and you can now edit the IDE’s theme colors directly without an extension. (Priorities, sure, but I know people who have waited longer for that last one than for union types.)

Ecosystem: Aspire 13.4 and a Critter Stack that does not sleep

Aspire 13.4 landed on June 1. The headline is the TypeScript apphost going GA, which completes Aspire’s transformation from ”.NET orchestration tool” to “polyglot orchestration tool that happens to come from the .NET team”. Typed resource commands with results and noticeably more mature Kubernetes and AKS support round it out. Aspire keeps quietly becoming the answer to “how do I run this pile of services locally without a wiki page of setup steps”, and I keep being fine with that.

And then there is the Critter Stack, which shipped its big 2026 GA wave in May and apparently used June to sprint instead of catching its breath. Wolverine crossed five million downloads on June 3, and in the last week of June alone (June 22 to 29) the team shipped three Wolverine releases (6.14 to 6.16), three Marten releases (9.10 to 9.12), and three Polecat releases. Two things in that wave stand out:

  • Wolverine can now talk natively to NServiceBus and MassTransit applications over their database transports (NServiceBus on SQL Server and PostgreSQL, MassTransit on PostgreSQL). That sounds like a niche interop feature until you realize what it is for: you can introduce Wolverine into an existing MassTransit or NServiceBus shop incrementally, service by service, over infrastructure both sides already trust. With MassTransit going commercial, an incremental migration path is exactly what a lot of teams were waiting for.
  • CritterWatch hit 1.0 beta, the monitoring and management dashboard for the whole stack, fed by new OpenTelemetry counters, diagnostics descriptors, and connection-state reporting across Wolverine and Marten. Together with a database queue performance fix that took SQL Server throughput from double digits to tens of thousands of messages per second, the stack’s operations story is growing up fast.

Also in the wave: Marten picked up declarative range partitioning for document tables, which turns the classic time-series retention pattern (partition by time, drop old partitions) from a hand-written script into a fluent API call.

What June was, really

June was the month a twenty-year-old wish item became a compiler feature. Build delivered its AI keynotes, and some of it will even matter, but public union Pet(Cat, Dog, Bird); compiling in a shipped preview SDK is the thing from June 2026 that will still be shaping codebases in ten years. Add an installer story that finally treats SDK management as a solved problem, an EF analyzer that catches sync-over-async before production does, and a Copilot cost meter for the metered era, and you get a month where the platform got better at the unglamorous things. Those are my favorite months.

Sources

Read the original on gingter.org

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.