Repository navigation
Tag helpers not bound for elements after the first in a @section body (10.0.400 regression) #13235
Description
Summary
In SDK 10.0.400, the Razor source generator stops binding tag helpers to elements inside a @section body after the first one. Those elements are emitted as raw literals instead, so UrlResolutionTagHelper never runs and app-relative ~/ URLs reach the response verbatim.
This does not reproduce on 10.0.302.
It is a silent failure: the build succeeds with no warning, the page renders, and the only visible effect is that browsers request ~/... relative to the current URL and get a 404. In our case an unattended SDK feature-band roll on CI took production stylesheets offline for eight days before anyone connected the two.
Repro
Pages/Shared/_L.cshtml
<!DOCTYPE html>
<html><head>
@RenderSection("Head", required: false)
</head><body>@RenderBody()</body></html>Pages/Repro.cshtml
@page
@{ Layout = "_L"; }
@section Head {
<link rel="stylesheet" href="~/insection-first.css">
<link rel="stylesheet" href="~/insection-second.css">
<link rel="stylesheet" href="~/insection-third.css" />
}
<link rel="stylesheet" href="~/toplevel-first.css">
<link rel="stylesheet" href="~/toplevel-second.css">
<a href="~/toplevel-anchor">anchor after a void element</a>dotnet new webapp, drop those two files in, dotnet run, GET /Repro.
Actual (10.0.400)
<link rel="stylesheet" href="/insection-first.css">
<link rel="stylesheet" href="~/insection-second.css">
<link rel="stylesheet" href="~/insection-third.css" />
</head><body><link rel="stylesheet" href="/toplevel-first.css">
<link rel="stylesheet" href="/toplevel-second.css">
<a href="/toplevel-anchor">anchor after a void element</a>Only the first element in the section is resolved. Everything at page top level is fine, including an <a href> following two void elements — so this is scoped to the DefineSection lambda, not to void elements in general.
Expected (and actual on 10.0.302)
All six URLs resolved to /....
Generated code
Building the same page with -p:EmitCompilerGeneratedFiles=true and counting instantiations in Repro_cshtml.g.cs:
| SDK | CreateTagHelper<UrlResolutionTagHelper>() |
section hrefs emitted via WriteLiteral |
|---|---|---|
| 10.0.302 | 3 | 0 |
| 10.0.400 | 1 | 2 (~/insection-second.css, ~/insection-third.css) |
On 10.0.400 the second and third elements are gone from the tag helper pipeline entirely — no scopeManager.Begin(...), no CreateTagHelper, just literal output.
Trigger condition
The first element in the section is emitted as TagMode.StartTagOnly — a void element written without a self-closing slash and without an end tag:
<link rel="stylesheet" href="~/a.css">Sections whose first element is self-closing (<link ... />) or has an explicit end tag (<script ...></script>) are unaffected, and every element in them binds normally. That is what made it so confusing in a real app: one @section on a page broke while its sibling section, and every <script src="~/...">, kept working.
Impact beyond URL resolution
UrlResolutionTagHelper is just the most visible casualty because the damage ends up in the HTML. Any tag helper is dropped the same way, so asp-for, asp-page and asp-append-version inside a section are equally affected — with failure modes that are considerably harder to notice than a 404 on a stylesheet.
Environment
- Broken: SDK 10.0.400 (Windows x64)
- Working: SDK 10.0.302
- ASP.NET Core Razor Pages,
net10.0, default_ViewImports.cshtmlwith@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - No Razor runtime compilation; source generator only
Workaround
Pin global.json to the 10.0.3xx feature band. Self-closing the first element in each section also avoids the trigger, but that relies on authors knowing about it, and it does not help the asp-* cases in sections whose first element is void.
Activity
davidwengier commentedon Aug 20, 2026
All these AIs write really detailed issues, but they never look for duplicates?
This was fixed by dotnet/roslyn#84771 and backported to 10.0.4xx in dotnet/roslyn#84782.
sts-001 commentedon Aug 20, 2026
Duplicate — already fixed. Apologies for not searching before filing; that's on me.
For anyone landing here from a search: fixed by dotnet/roslyn#84771 ("Resolve consecutive WithoutEndTag tag helpers as siblings"), backported to the 10.0.4xx band in dotnet/roslyn#84782. That title also explains the trigger condition I described empirically — consecutive elements with no end tag were being treated as nested rather than as siblings, so everything after the first lost its tag-helper binding.
Workaround until you are on an SDK carrying the backport: pin global.json to a feature band that predates the regression.