Skip to content

Tag helpers not bound for elements after the first in a @section body (10.0.400 regression) #13235

Closed

Description

@sts-001

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.cshtml with @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

  1. davidwengier commented on Aug 20, 2026

    @davidwengier
    Member

    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.

  2. sts-001 commented on Aug 20, 2026

    @sts-001
    Author

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions