🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
VS2026 is now supported - what we changed and what we learned
Created by Hans.karlsen on 2026-01-11 · Last edited by Hans.karlsen on 2026-01-11.

(The changes described applies to VS2022 also as of builds in 2026 and onwards, no new VSIX download, can run side by side VS2022, VS2026)

How the GAC masked the real problems, how NuGet exposed them, and how we finally fixed the root cause

Over the last development cycle, we’ve finally untangled one of the most persistent and subtle problems in the Visual Studio integration story for MDriven: load‑context conflicts. These issues have existed for years, but they were largely invisible until we moved away from the Global Assembly Cache (GAC) and fully embraced NuGet distribution.

VS2026 gave us the opportunity—and the pressure—to understand the problem completely and fix it at the foundation.

🧩 The Hidden Simplicity of the GAC Era

Before NuGet became the standard way to deliver MDriven updates, Visual Studio relied heavily on the GAC. That meant:

  • There was exactly one version of each MDriven assembly on the machine
  • Visual Studio always loaded that version
  • The project also loaded that version
  • All types came from the same physical file
  • Load‑context issues simply could not occur

This uniformity made many complexities disappear. But it came at a huge cost:

  • You couldn’t easily ship new versions
  • You couldn’t have per‑project versioning
  • You couldn’t reliably test different versions side‑by‑side
  • You couldn’t use NuGet the way modern .NET development expects

The GAC made things look stable, but it also froze the ecosystem.

🚧 The Moment Everything Broke: Leaving the GAC

When we removed the GAC dependency and fully supported NuGet, Visual Studio suddenly had two independent sources for MDriven assemblies:

  • The user’s project (NuGet)
  • The VSIX plugin folder

And because they had the same name and the same public key, Visual Studio happily loaded:

  • MDriven.Handles from the project
  • MDriven.Handles from the VSIX

…into two different load contexts.

From Visual Studio’s perspective:

  • TypeA from the project ≠ TypeA from the VSIX
  • Even if the bytes were identical
  • Even if the versions matched
  • Even if everything “should” work

This was the silent root cause behind:

  • Reflection failures
  • Designer crashes
  • Code‑gen errors like “.AddRange does not exist”
  • Random behavior depending on load order
  • Years of unpredictable designer instability

The GAC had masked the problem. NuGet exposed it brutally.

🔑 The Breakthrough: Give the VSIX Its Own Assembly Identity

The real fix was to ensure that Visual Studio could never confuse the two worlds again.

We changed the signing key for all design‑time assemblies in the VSIX:

  • Runtime/NuGet assemblies: PublicKeyToken=46a833be9e90de8c
  • Design‑time/VSIX assemblies: PublicKeyToken=8284d47cc38744ec

This guarantees:

  • The VSIX loads its own assemblies
  • The project loads its own assemblies
  • Visual Studio never merges or cross‑binds them
  • Load‑context conflicts disappear entirely

If developers encounter assemblies signed with the design‑time key: They are intentional, safe, and required for Visual Studio stability.

🔄 The Second Breakthrough: Only Transport Simple Data Across the Boundary

Once the load‑context separation was in place, the next insight became obvious:

Never pass project‑loaded objects directly into the VSIX designers.

Instead:

  • Extract simple DTOs from the project
  • Send those DTOs into the designer
  • Let the designer operate in its own isolated world
  • Send DTOs back after design
  • Rehydrate them into real project objects

This eliminates all cross‑context type confusion.

🧠 We Actually Learned This Earlier—But Only Partially

Back in VS2022, when .NET 6 WinForms designers moved out‑of‑process, we were forced to adopt a DTO strategy for that designer. It worked beautifully.

But the rest of the designers—especially .NET Framework 4.8—were still in‑process, so the old patterns persisted.

With VS2026, we finally unified the approach:

All designers now use the DTO strategy.

Even .NET 4.8 designers. Even legacy designers. Everything.

And suddenly:

  • The long‑standing code‑gen issues disappeared
  • Designer reliability improved dramatically
  • The extension became predictable instead of mystical

🌅 The Light at the End of the VSIX Tunnel

This has been a long journey—years of odd behavior, reflection quirks, and designer inconsistencies. But with:

  • Unique design‑time assemblies
  • A strict DTO boundary
  • Unified handling across all designers
  • A clean separation between runtime and design‑time worlds
  • A modern NuGet‑friendly architecture

…we finally have a stable foundation for the future.

The VS2026 VSIX is the most robust, predictable, and maintainable version we’ve ever shipped.

And for the first time in a long time, we can say with confidence:

We finally see the light in the long VSIX tunnel.

🧭 A Cleaner Path for the OCL Editor: Direct TypeSystem From the Modlr‑Model

Historically, the OCL editor inside EcoHandles (WinForms) obtained its model information by reflecting the generated code and extracting the IEcoTypeSystem from the compiled EcoSpace. That approach worked, but it had two major drawbacks:

  1. It crossed the Project ↔ VSIX boundary using real types, which we now avoid completely.
  2. It forced a full codegen + compile cycle before the OCL editor could see any model changes.

With the new architecture, that approach no longer fits. Since we now enforce a strict DTO boundary between the project world and the VSIX world, we needed a cleaner, safer, and more predictable way to supply the OCL editor with model metadata.

The new approach is much simpler:

We now take the IEcoTypeSystem directly from your Modlr‑Model.

This gives you a dramatically better experience:

  • You can edit your model
  • Save it
  • And instantly see the updated types in the OCL editor
  • No codegen, no compile, no waiting

The only requirement is that your Modlr‑Model is open while you work in the OCL editor. Given the speed and clarity this provides, it’s a very small price to pay.

⚠️ A Small but Important GOTCHA: Packages

The Modlr‑Model’s type system always includes all packages defined in the model. However, your runtime EcoSpace can be configured to use only a subset of those packages.

This feature was originally intended to reduce the size of the runtime type system, but in practice:

  • It adds complexity
  • It creates mismatches between design‑time and runtime
  • It causes confusing runtime errors when parts of the model “disappear”
  • And it provides very little real benefit

Our recommendation is simple:

Always include all packages in your EcoSpace.

This ensures:

  • The OCL editor sees the same model as your runtime
  • No missing classes or associations
  • No “why does this work in the designer but not at runtime” mysteries
  • A consistent, predictable modeling experience