Summary
The Razor source generator in .NET 11 Preview 3 (11.0.100-preview.3.26209.122) emits synthetic members with empty identifier names when a .razor file contains a switch expression that returns RenderFragment lambdas with inline Razor markup. This produces CS0101/CS0102 errors with empty '' names, and the resulting failure cascades through the rest of the file — CS0246 for every type referenced (including @inject services and inline-defined enums) and, in larger files with multiple @inject directives, a swarm of CS9348: The compilation unit cannot directly contain members.
The same code compiles cleanly under .NET 10 GA.
Repro
dotnet new maui-blazor, add the following file:
Pages/RazorSgRepro.razor
@page "/repro"
@inject NavigationManager Nav
<PageTitle>RazorSgRepro</PageTitle>
<h1>Razor SG Regression Repro</h1>
<div>@RenderBadge(SampleType.Alpha)</div>
<div>@RenderBadge(SampleType.Beta)</div>
<div>@RenderBadge(SampleType.Gamma)</div>
@code {
public enum SampleType { Alpha, Beta, Gamma }
private static RenderFragment RenderBadge(SampleType type) => type switch
{
SampleType.Alpha => (__builder) =>
{
<span class="badge bg-primary"><i class="bi bi-fonts me-1"></i>Alpha</span>
},
SampleType.Beta => (__builder) =>
{
<span class="badge bg-secondary"><i class="bi bi-chat-quote me-1"></i>Beta</span>
},
_ => (__builder) =>
{
<span class="badge bg-light">Unknown</span>
}
};
}
Pin the SDK via global.json:
{ "sdk": { "version": "11.0.100-preview.3.26209.122", "rollForward": "latestFeature", "allowPrerelease": true } }
Then:
dotnet clean && rm -rf */obj */bin
dotnet build
A complete minimal solution (zipped) is attached below as peethree-net11p3-repro.zip.
Expected
Build succeeds, as it does under .NET 10 GA.
Actual
Build fails with the following error fingerprint:
Pages/RazorSgRepro.razor(23,54): error CS0101: The namespace '...Pages' already contains a definition for ''
Pages/RazorSgRepro.razor(19,52): error CS0102: The type 'RazorSgRepro' already contains a definition for ''
Pages/RazorSgRepro.razor(2,9): error CS0246: The type or namespace name 'NavigationManager' could not be found
Pages/RazorSgRepro.razor(21,9): error CS0246: The type or namespace name 'SampleType' could not be found
The diagnostic signature — CS0101 / CS0102 reporting duplicate definitions with EMPTY names — points squarely at the Razor SG: it is synthesizing the per-arm RenderFragment member without assigning a stable identifier when the lambda body contains inline Razor markup.
In larger production files (we hit this in a 1168-line .razor page with 10 @inject directives), the SG appears to give up on the file entirely and emits the injected fields at compilation-unit scope, producing 31 errors dominated by CS9348: The compilation unit cannot directly contain members on every @inject line, plus the empty-name CS0101/CS0102 collisions and cascading CS0246 on every injected type. The minimal repro above is the smallest form that still produces the empty-name SG fingerprint.
Workaround
Either (a) extract each switch arm to a separately-named RenderFragment helper:
private static RenderFragment RenderBadge(SampleType type) => type switch
{
SampleType.Alpha => RenderAlpha(),
SampleType.Beta => RenderBeta(),
_ => RenderUnknown(),
};
private static RenderFragment RenderAlpha() => @<span class="badge bg-primary">Alpha</span>;
…or (b) replace the RenderFragment-returning helper with a tuple-returning meta helper and inline the markup at the call site:
private static (string CssClass, string Label) GetBadge(SampleType type) => type switch
{
SampleType.Alpha => ("bg-primary", "Alpha"),
SampleType.Beta => ("bg-secondary", "Beta"),
_ => ("bg-light", "Unknown"),
};
@{ var b = GetBadge(type); }
<span class="badge @b.CssClass">@b.Label</span>
Both workarounds compile under net11p3 and net10 GA.
Environment
- OS: macOS 15.x (Darwin), Apple Silicon
- SDK that fails:
11.0.100-preview.3.26209.122
- SDK that works:
10.0.101 (.NET 10 GA)
- Project type:
dotnet new maui-blazor (MAUI Blazor Hybrid + Web), Razor SG running against the .Shared project
- Reproduces with full clean (
rm -rf */obj */bin) — not a stale cache.
Attachments
- Build log: see body above (full log: ~3KB)
- Minimal solution zip:
peethree-net11p3-repro.zip (252KB)
peethree-net11p3-repro.zip
Summary
The Razor source generator in .NET 11 Preview 3 (
11.0.100-preview.3.26209.122) emits synthetic members with empty identifier names when a.razorfile contains a switch expression that returnsRenderFragmentlambdas with inline Razor markup. This producesCS0101/CS0102errors with empty''names, and the resulting failure cascades through the rest of the file —CS0246for every type referenced (including@injectservices and inline-defined enums) and, in larger files with multiple@injectdirectives, a swarm ofCS9348: The compilation unit cannot directly contain members.The same code compiles cleanly under .NET 10 GA.
Repro
dotnet new maui-blazor, add the following file:Pages/RazorSgRepro.razorPin the SDK via
global.json:{ "sdk": { "version": "11.0.100-preview.3.26209.122", "rollForward": "latestFeature", "allowPrerelease": true } }Then:
A complete minimal solution (zipped) is attached below as
peethree-net11p3-repro.zip.Expected
Build succeeds, as it does under .NET 10 GA.
Actual
Build fails with the following error fingerprint:
The diagnostic signature —
CS0101/CS0102reporting duplicate definitions with EMPTY names — points squarely at the Razor SG: it is synthesizing the per-armRenderFragmentmember without assigning a stable identifier when the lambda body contains inline Razor markup.In larger production files (we hit this in a 1168-line
.razorpage with 10@injectdirectives), the SG appears to give up on the file entirely and emits the injected fields at compilation-unit scope, producing 31 errors dominated byCS9348: The compilation unit cannot directly contain memberson every@injectline, plus the empty-name CS0101/CS0102 collisions and cascading CS0246 on every injected type. The minimal repro above is the smallest form that still produces the empty-name SG fingerprint.Workaround
Either (a) extract each switch arm to a separately-named
RenderFragmenthelper:…or (b) replace the
RenderFragment-returning helper with a tuple-returning meta helper and inline the markup at the call site:Both workarounds compile under net11p3 and net10 GA.
Environment
11.0.100-preview.3.26209.12210.0.101(.NET 10 GA)dotnet new maui-blazor(MAUI Blazor Hybrid + Web), Razor SG running against the.Sharedprojectrm -rf */obj */bin) — not a stale cache.Attachments
peethree-net11p3-repro.zip(252KB)peethree-net11p3-repro.zip