From 20d902354dad18854e2286da47c5dfa501fb448f Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 5 Aug 2026 18:35:20 +0200 Subject: [PATCH 1/3] Add asset path metadata attributes Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b17d3f77-bb29-4f1d-8c96-c29347281928 --- .../src/AcceptsAssetPathAttribute.cs | 46 +++++++++++++++++++ .../Components/src/AssetPathAttribute.cs | 22 +++++++++ .../Components/src/PublicAPI.Unshipped.txt | 6 +++ .../Web/src/PublicAPI.Unshipped.txt | 1 + .../Web/src/Web/AssetPathAttributes.cs | 18 ++++++++ .../Web/test/AssetPathAttributesTest.cs | 27 +++++++++++ 6 files changed, 120 insertions(+) create mode 100644 src/Components/Components/src/AcceptsAssetPathAttribute.cs create mode 100644 src/Components/Components/src/AssetPathAttribute.cs create mode 100644 src/Components/Web/src/Web/AssetPathAttributes.cs create mode 100644 src/Components/Web/test/AssetPathAttributesTest.cs diff --git a/src/Components/Components/src/AcceptsAssetPathAttribute.cs b/src/Components/Components/src/AcceptsAssetPathAttribute.cs new file mode 100644 index 000000000000..954b470a6d4b --- /dev/null +++ b/src/Components/Components/src/AcceptsAssetPathAttribute.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components; + +/// +/// Declares an HTML element and attribute combination that accepts static asset-path expansion. +/// +/// +/// The Razor compiler discovers this metadata on public classes named AssetPathAttributes. +/// +/// +/// +/// [AcceptsAssetPath("img", "src")] +/// public static class AssetPathAttributes +/// { +/// } +/// +/// +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] +public sealed class AcceptsAssetPathAttribute : Attribute +{ + /// + /// Initializes a new instance of . + /// + /// The HTML element name. + /// The HTML attribute name. + public AcceptsAssetPathAttribute(string elementName, string attributeName) + { + ArgumentNullException.ThrowIfNull(elementName); + ArgumentNullException.ThrowIfNull(attributeName); + + ElementName = elementName; + AttributeName = attributeName; + } + + /// + /// Gets the HTML element name. + /// + public string ElementName { get; } + + /// + /// Gets the HTML attribute name. + /// + public string AttributeName { get; } +} diff --git a/src/Components/Components/src/AssetPathAttribute.cs b/src/Components/Components/src/AssetPathAttribute.cs new file mode 100644 index 000000000000..35443a5ab95a --- /dev/null +++ b/src/Components/Components/src/AssetPathAttribute.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components; + +/// +/// Indicates that a component parameter accepts a static asset path that the Razor compiler can expand. +/// +/// +/// This attribute is valid only on properties that are also marked with . +/// +/// +/// +/// [Parameter] +/// [AssetPath] +/// public string? Source { get; set; } +/// +/// +[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] +public sealed class AssetPathAttribute : Attribute +{ +} diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index 626f6b5fb93e..d28242fc4cd2 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -1,4 +1,10 @@ #nullable enable +Microsoft.AspNetCore.Components.AcceptsAssetPathAttribute +Microsoft.AspNetCore.Components.AcceptsAssetPathAttribute.AcceptsAssetPathAttribute(string! elementName, string! attributeName) -> void +Microsoft.AspNetCore.Components.AcceptsAssetPathAttribute.AttributeName.get -> string! +Microsoft.AspNetCore.Components.AcceptsAssetPathAttribute.ElementName.get -> string! +Microsoft.AspNetCore.Components.AssetPathAttribute +Microsoft.AspNetCore.Components.AssetPathAttribute.AssetPathAttribute() -> void Microsoft.AspNetCore.Components.CacheBehavior Microsoft.AspNetCore.Components.CacheBehavior.Rerender = 0 -> Microsoft.AspNetCore.Components.CacheBehavior Microsoft.AspNetCore.Components.CacheBehavior.Throw = 1 -> Microsoft.AspNetCore.Components.CacheBehavior diff --git a/src/Components/Web/src/PublicAPI.Unshipped.txt b/src/Components/Web/src/PublicAPI.Unshipped.txt index 37f5a9d97a14..46490b563f38 100644 --- a/src/Components/Web/src/PublicAPI.Unshipped.txt +++ b/src/Components/Web/src/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable +Microsoft.AspNetCore.Components.Web.AssetPathAttributes Microsoft.AspNetCore.Components.Web.EnvironmentView Microsoft.AspNetCore.Components.Web.EnvironmentView.ChildContent.get -> Microsoft.AspNetCore.Components.RenderFragment? Microsoft.AspNetCore.Components.Web.EnvironmentView.ChildContent.set -> void diff --git a/src/Components/Web/src/Web/AssetPathAttributes.cs b/src/Components/Web/src/Web/AssetPathAttributes.cs new file mode 100644 index 000000000000..0998b899e23f --- /dev/null +++ b/src/Components/Web/src/Web/AssetPathAttributes.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.Components.Web; + +/// +/// Infrastructure for the discovery of HTML attributes that accept static asset-path expansion. +/// +/// +/// To extend the supported element and attribute combinations, define a public class named +/// AssetPathAttributes and annotate it with . +/// +[AcceptsAssetPath("img", "src")] +[AcceptsAssetPath("link", "href")] +[AcceptsAssetPath("script", "src")] +public static class AssetPathAttributes +{ +} diff --git a/src/Components/Web/test/AssetPathAttributesTest.cs b/src/Components/Web/test/AssetPathAttributesTest.cs new file mode 100644 index 000000000000..5efc87fc9cbb --- /dev/null +++ b/src/Components/Web/test/AssetPathAttributesTest.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection; + +namespace Microsoft.AspNetCore.Components.Web; + +public class AssetPathAttributesTest +{ + [Fact] + public void DeclaresBuiltInAssetPathMappings() + { + var mappings = typeof(AssetPathAttributes) + .GetCustomAttributes() + .Select(attribute => (attribute.ElementName, attribute.AttributeName)) + .OrderBy(mapping => mapping.ElementName) + .ToArray(); + + Assert.Equal( + [ + ("img", "src"), + ("link", "href"), + ("script", "src"), + ], + mappings); + } +} From ae5b14ae64f8d49e006713c60aed4319be1ae1d7 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 5 Aug 2026 18:36:37 +0200 Subject: [PATCH 2/3] Remove premature asset path metadata test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b17d3f77-bb29-4f1d-8c96-c29347281928 --- .../Web/test/AssetPathAttributesTest.cs | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/Components/Web/test/AssetPathAttributesTest.cs diff --git a/src/Components/Web/test/AssetPathAttributesTest.cs b/src/Components/Web/test/AssetPathAttributesTest.cs deleted file mode 100644 index 5efc87fc9cbb..000000000000 --- a/src/Components/Web/test/AssetPathAttributesTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection; - -namespace Microsoft.AspNetCore.Components.Web; - -public class AssetPathAttributesTest -{ - [Fact] - public void DeclaresBuiltInAssetPathMappings() - { - var mappings = typeof(AssetPathAttributes) - .GetCustomAttributes() - .Select(attribute => (attribute.ElementName, attribute.AttributeName)) - .OrderBy(mapping => mapping.ElementName) - .ToArray(); - - Assert.Equal( - [ - ("img", "src"), - ("link", "href"), - ("script", "src"), - ], - mappings); - } -} From b112b42091bcc602061f2731dedba9bdd30df26f Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 5 Aug 2026 18:53:50 +0200 Subject: [PATCH 3/3] Expand built-in asset path metadata Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b17d3f77-bb29-4f1d-8c96-c29347281928 --- src/Components/Web/src/Web/AssetPathAttributes.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Components/Web/src/Web/AssetPathAttributes.cs b/src/Components/Web/src/Web/AssetPathAttributes.cs index 0998b899e23f..26e10b4e3610 100644 --- a/src/Components/Web/src/Web/AssetPathAttributes.cs +++ b/src/Components/Web/src/Web/AssetPathAttributes.cs @@ -10,9 +10,15 @@ namespace Microsoft.AspNetCore.Components.Web; /// To extend the supported element and attribute combinations, define a public class named /// AssetPathAttributes and annotate it with . /// +[AcceptsAssetPath("audio", "src")] [AcceptsAssetPath("img", "src")] +[AcceptsAssetPath("input", "src")] [AcceptsAssetPath("link", "href")] [AcceptsAssetPath("script", "src")] +[AcceptsAssetPath("source", "src")] +[AcceptsAssetPath("track", "src")] +[AcceptsAssetPath("video", "poster")] +[AcceptsAssetPath("video", "src")] public static class AssetPathAttributes { }