diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs
index 7de5cb4582..8d3166a88e 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentBindLoweringPass.cs
@@ -275,6 +275,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
out var valueAttributeName,
out var changeAttributeName,
out var expressionAttributeName,
+ out var changeAttributeNode,
out var valueAttribute,
out var changeAttribute,
out var expressionAttribute))
@@ -393,12 +394,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
[ComponentMetadata.Common.OriginalAttributeName] = node.OriginalAttributeName,
},
AttributeName = changeAttributeName,
+ AttributeNameExpression = changeAttributeNode,
Source = node.Source,
Prefix = changeAttributeName + "=\"",
Suffix = "\"",
- EventUpdatesAttributeName = valueNode.AttributeName,
+ EventUpdatesAttributeName = valueAttributeName,
};
changeNode.Children.Add(new CSharpExpressionAttributeValueIntermediateNode());
@@ -510,6 +512,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
out string valueAttributeName,
out string changeAttributeName,
out string expressionAttributeName,
+ out CSharpExpressionIntermediateNode changeAttributeNode,
out BoundAttributeDescriptor valueAttribute,
out BoundAttributeDescriptor changeAttribute,
out BoundAttributeDescriptor expressionAttribute)
@@ -517,10 +520,20 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
valueAttributeName = null;
changeAttributeName = null;
expressionAttributeName = null;
+ changeAttributeNode = null;
valueAttribute = null;
changeAttribute = null;
expressionAttribute = null;
+ // The tag helper specifies attribute names, they should win.
+ //
+ // This handles cases like where the tag helper is
+ // generated to match a specific tag and has metadata that identify the attributes.
+ //
+ // We expect 1 bind tag helper per-node.
+ var node = bindEntry.BindNode;
+ var attributeName = node.AttributeName;
+
// Even though some of our 'bind' tag helpers specify the attribute names, they
// should still satisfy one of the valid syntaxes.
if (!TryParseBindAttribute(bindEntry, out valueAttributeName))
@@ -528,24 +541,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
return false;
}
- if (bindEntry.BindEventNode != null)
- {
- changeAttributeName = GetAttributeContent(bindEntry.BindEventNode)?.Content?.Trim('"');
- }
-
- // The tag helper specifies attribute names, they should win.
- //
- // This handles cases like where the tag helper is
- // generated to match a specific tag and has metadata that identify the attributes.
- //
- // We expect 1 bind tag helper per-node.
- var node = bindEntry.BindNode;
- var attributeName = node.AttributeName;
valueAttributeName = node.TagHelper.GetValueAttributeName() ?? valueAttributeName;
// If there an attribute that specifies the event like @bind:event="oninput",
// that should be preferred. Otherwise, use the one from the tag helper.
- changeAttributeName ??= node.TagHelper.GetChangeAttributeName();
+ if (bindEntry.BindEventNode == null)
+ {
+ // @bind:event not specified
+ changeAttributeName ??= node.TagHelper.GetChangeAttributeName();
+ }
+ else if (TryExtractEventNodeStaticText(bindEntry.BindEventNode, out var text))
+ {
+ // @bind:event="oninput" - change attribute is static
+ changeAttributeName = text;
+ }
+ else
+ {
+ // @bind:event="@someExpr" - we can't know the name of the change attribute, it's dynamic
+ changeAttributeNode = ExtractEventNodeExpression(bindEntry.BindEventNode);
+ }
expressionAttributeName = node.TagHelper.GetExpressionAttributeName();
@@ -554,7 +568,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
if (componentTagHelper == null)
{
// If it's not a component node then there isn't too much else to figure out.
- return attributeName != null && changeAttributeName != null;
+ return attributeName != null && (changeAttributeName != null || changeAttributeNode != null);
}
// If this is a component, we need an attribute name for the value.
@@ -597,6 +611,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
return true;
+
+ static bool TryExtractEventNodeStaticText(TagHelperDirectiveAttributeParameterIntermediateNode node, out string text)
+ {
+ if (node.Children[0] is HtmlContentIntermediateNode html)
+ {
+ text = GetAttributeContent(html).Content;
+ return true;
+ }
+
+ text = null;
+ return false;
+ }
+
+ static CSharpExpressionIntermediateNode ExtractEventNodeExpression(TagHelperDirectiveAttributeParameterIntermediateNode node)
+ {
+ if (node.Children[0] is CSharpExpressionIntermediateNode expression)
+ {
+ return expression;
+ }
+
+ return null;
+ }
}
private void RewriteNodesForComponentDelegateBind(
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
index 78cdcc5496..dab006906c 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
@@ -85,6 +85,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(node));
}
+ WriteCSharpExpressionInnards(context, node);
+ }
+
+ private void WriteCSharpExpressionInnards(CodeRenderingContext context, CSharpExpressionIntermediateNode node, string type = null)
+ {
if (node.Children.Count == 0)
{
return;
@@ -95,9 +100,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
using (context.CodeWriter.BuildLinePragma(node.Source.Value, context))
{
var offset = DesignTimeVariable.Length + " = ".Length;
+
+ if (type != null)
+ {
+ offset += type.Length + 2; // two parenthesis
+ }
+
context.CodeWriter.WritePadding(offset, node.Source, context);
context.CodeWriter.WriteStartAssignment(DesignTimeVariable);
+ if (type != null)
+ {
+ context.CodeWriter.Write("(");
+ context.CodeWriter.Write(type);
+ context.CodeWriter.Write(")");
+ }
+
for (var i = 0; i < node.Children.Count; i++)
{
if (node.Children[i] is IntermediateToken token && token.IsCSharp)
@@ -209,6 +227,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(node));
}
+ // This expression may contain code so we have to render it or else the design-time
+ // exprience is broken.
+ if (node.AttributeNameExpression is CSharpExpressionIntermediateNode expression)
+ {
+ WriteCSharpExpressionInnards(context, expression, "string");
+ }
+
context.RenderChildren(node);
}
@@ -275,11 +300,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// Do nothing
}
- protected override void BeginWriteAttribute(CodeWriter codeWriter, string key)
+ protected override void BeginWriteAttribute(CodeRenderingContext context, string key)
{
- if (codeWriter == null)
+ if (context == null)
{
- throw new ArgumentNullException(nameof(codeWriter));
+ throw new ArgumentNullException(nameof(context));
}
if (key == null)
@@ -287,7 +312,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(key));
}
- codeWriter
+ context.CodeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{nameof(ComponentsApi.RenderTreeBuilder.AddAttribute)}")
.Write("-1")
.WriteParameterSeparator()
@@ -295,6 +320,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
.WriteParameterSeparator();
}
+ protected override void BeginWriteAttribute(CodeRenderingContext context, IntermediateNode expression)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (expression == null)
+ {
+ throw new ArgumentNullException(nameof(expression));
+ }
+
+ context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddAttribute}");
+ context.CodeWriter.Write("-1");
+ context.CodeWriter.WriteParameterSeparator();
+
+ var tokens = GetCSharpTokens(expression);
+ for (var i = 0; i < tokens.Count; i++)
+ {
+ context.CodeWriter.Write(tokens[i].Content);
+ }
+
+ context.CodeWriter.WriteParameterSeparator();
+ }
+
public override void WriteComponent(CodeRenderingContext context, ComponentIntermediateNode node)
{
if (context == null)
@@ -679,7 +729,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// __builder.AddAttribute(1, "ChildContent", (RenderFragment)((__builder73) => { ... }));
// OR
// __builder.AddAttribute(1, "ChildContent", (RenderFragment)((person) => (__builder73) => { ... }));
- BeginWriteAttribute(context.CodeWriter, node.AttributeName);
+ BeginWriteAttribute(context, node.AttributeName);
context.CodeWriter.Write($"({node.TypeName})(");
WriteComponentChildContentInnards(context, node);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
index e2b224db7a..df21a531fa 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentNodeWriter.cs
@@ -12,7 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
{
internal abstract class ComponentNodeWriter : IntermediateNodeWriter, ITemplateTargetExtension
{
- protected abstract void BeginWriteAttribute(CodeWriter codeWriter, string key);
+ protected abstract void BeginWriteAttribute(CodeRenderingContext context, string key);
+
+ protected abstract void BeginWriteAttribute(CodeRenderingContext context, IntermediateNode expression);
protected abstract void WriteReferenceCaptureInnards(CodeRenderingContext context, ReferenceCaptureIntermediateNode node, bool shouldTypeCheck);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
index c2ae3e539b..6d49082b4a 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs
@@ -233,7 +233,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
Debug.Assert(_currentAttributeValues.Count == 0);
context.RenderChildren(node);
- WriteAttribute(context, node.AttributeName, _currentAttributeValues);
+ if (node.AttributeNameExpression == null)
+ {
+ WriteAttribute(context, node.AttributeName, _currentAttributeValues);
+ }
+ else
+ {
+ WriteAttribute(context, node.AttributeNameExpression, _currentAttributeValues);
+ }
_currentAttributeValues.Clear();
if (!string.IsNullOrEmpty(node.EventUpdatesAttributeName))
@@ -659,7 +666,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
// _builder.AddAttribute(1, "ChildContent", (RenderFragment)((__builder73) => { ... }));
// OR
// _builder.AddAttribute(1, "ChildContent", (RenderFragment)((person) => (__builder73) => { ... }));
- BeginWriteAttribute(context.CodeWriter, node.AttributeName);
+ BeginWriteAttribute(context, node.AttributeName);
context.CodeWriter.Write($"({node.TypeName})(");
WriteComponentChildContentInnards(context, node);
@@ -837,14 +844,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
private void WriteAttribute(CodeRenderingContext context, string key, IList value)
{
- BeginWriteAttribute(context.CodeWriter, key);
+ BeginWriteAttribute(context, key);
WriteAttributeValue(context, value);
context.CodeWriter.WriteEndMethodInvocation();
}
- protected override void BeginWriteAttribute(CodeWriter codeWriter, string key)
+ private void WriteAttribute(CodeRenderingContext context, IntermediateNode nameExpression, IList value)
{
- codeWriter
+ BeginWriteAttribute(context, nameExpression);
+ WriteAttributeValue(context, value);
+ context.CodeWriter.WriteEndMethodInvocation();
+ }
+
+ protected override void BeginWriteAttribute(CodeRenderingContext context, string key)
+ {
+ context.CodeWriter
.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddAttribute}")
.Write((_sourceSequence++).ToString())
.WriteParameterSeparator()
@@ -852,6 +866,21 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
.WriteParameterSeparator();
}
+ protected override void BeginWriteAttribute(CodeRenderingContext context, IntermediateNode nameExpression)
+ {
+ context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddAttribute}");
+ context.CodeWriter.Write((_sourceSequence++).ToString());
+ context.CodeWriter.WriteParameterSeparator();
+
+ var tokens = GetCSharpTokens(nameExpression);
+ for (var i = 0; i < tokens.Count; i++)
+ {
+ WriteCSharpToken(context, tokens[i]);
+ }
+
+ context.CodeWriter.WriteParameterSeparator();
+ }
+
private static string GetHtmlContent(HtmlContentIntermediateNode node)
{
var builder = new StringBuilder();
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/HtmlAttributeIntermediateNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/HtmlAttributeIntermediateNode.cs
index 8acbfcc90a..8fd1cc9df4 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/HtmlAttributeIntermediateNode.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Intermediate/HtmlAttributeIntermediateNode.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Linq;
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
@@ -9,6 +10,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
{
public override IntermediateNodeCollection Children { get; } = new IntermediateNodeCollection();
+ public CSharpExpressionIntermediateNode AttributeNameExpression { get; set; }
+
public string AttributeName { get; set; }
public string Prefix { get; set; }
@@ -32,6 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
formatter.WriteContent(AttributeName);
formatter.WriteProperty(nameof(AttributeName), AttributeName);
+ formatter.WriteProperty(nameof(AttributeNameExpression), string.Join(string.Empty, AttributeNameExpression?.FindDescendantNodes().Select(n => n.Content) ?? Array.Empty()));
formatter.WriteProperty(nameof(Prefix), Prefix);
formatter.WriteProperty(nameof(Suffix), Suffix);
formatter.WriteProperty(nameof(EventUpdatesAttributeName), EventUpdatesAttributeName);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
index 8e889fe94f..c99e39269e 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentCodeGenerationTestBase.cs
@@ -1011,6 +1011,64 @@ namespace Test
CompileToAssembly(generated);
}
+ [Fact]
+ public void BindToElement_WithEventAsExpression()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using System;
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ [BindElement(""div"", ""value"", ""myvalue"", ""myevent"")]
+ public static class BindAttributes
+ {
+ }
+}"));
+ // Act
+ var generated = CompileToCSharp(@"
+@{ var x = ""anotherevent""; }
+
+@code {
+ public string ParentValue { get; set; } = ""hi"";
+}");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
+ [Fact]
+ public void BindToElement_WithEventAsExplicitExpression()
+ {
+ // Arrange
+ AdditionalSyntaxTrees.Add(Parse(@"
+using System;
+using Microsoft.AspNetCore.Components;
+
+namespace Test
+{
+ [BindElement(""div"", ""value"", ""myvalue"", ""myevent"")]
+ public static class BindAttributes
+ {
+ }
+}"));
+ // Act
+ var generated = CompileToCSharp(@"
+@{ var x = ""anotherevent""; }
+
+@code {
+ public string ParentValue { get; set; } = ""hi"";
+}");
+
+ // Assert
+ AssertDocumentNodeMatchesBaseline(generated.CodeDocument);
+ AssertCSharpDocumentMatchesBaseline(generated.CodeDocument);
+ CompileToAssembly(generated);
+ }
+
[Fact]
public void BuiltIn_BindToInputWithoutType_WritesAttributes()
{
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..bcbcf21991
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,59 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public partial class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
+ {
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ var x = "anotherevent";
+
+#line default
+#line hidden
+#nullable disable
+ __o = Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ ParentValue
+
+#line default
+#line hidden
+#nullable disable
+ );
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ __o = (string)x.ToString();
+
+#line default
+#line hidden
+#nullable disable
+ __o = Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value, ParentValue);
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ public string ParentValue { get; set; } = "hi";
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..0fc0e38366
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,33 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public partial - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ CSharpCode - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var x = "anotherevent";
+ MarkupElement - (30:1,0 [70] x:\dir\subdir\Test\TestComponent.cshtml) - div
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - myvalue=" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+ IntermediateToken - (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - =" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value,
+ IntermediateToken - - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlContent - (100:1,70 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (100:1,70 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentValue { get; set; } = "hi";\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..d605e888a2
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,24 @@
+Source Location: (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+| var x = "anotherevent"; |
+Generated Location: (854:24,2 [25] )
+| var x = "anotherevent"; |
+
+Source Location: (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml)
+|ParentValue|
+Generated Location: (1098:32,19 [11] )
+|ParentValue|
+
+Source Location: (83:1,53 [12] x:\dir\subdir\Test\TestComponent.cshtml)
+|x.ToString()|
+Generated Location: (1300:40,53 [12] )
+|x.ToString()|
+
+Source Location: (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ public string ParentValue { get; set; } = "hi";
+|
+Generated Location: (1631:50,7 [55] )
+|
+ public string ParentValue { get; set; } = "hi";
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..f9a2e87af7
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs
@@ -0,0 +1,59 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public partial class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 219
+ private void __RazorDirectiveTokenHelpers__() {
+ }
+ #pragma warning restore 219
+ #pragma warning disable 0414
+ private static System.Object __o = null;
+ #pragma warning restore 0414
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
+ {
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ var x = "anotherevent";
+
+#line default
+#line hidden
+#nullable disable
+ __o = Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ ParentValue
+
+#line default
+#line hidden
+#nullable disable
+ );
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ __o = (string)x;
+
+#line default
+#line hidden
+#nullable disable
+ __o = Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value, ParentValue);
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ public string ParentValue { get; set; } = "hi";
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..d439ed52cd
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt
@@ -0,0 +1,33 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [12] ) - System
+ UsingDirective - (18:2,1 [32] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [17] ) - System.Linq
+ UsingDirective - (73:4,1 [28] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [37] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public partial - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ DesignTimeDirective -
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning disable 0414
+ CSharpCode -
+ IntermediateToken - - CSharp - private static System.Object __o = null;
+ CSharpCode -
+ IntermediateToken - - CSharp - #pragma warning restore 0414
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ CSharpCode - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var x = "anotherevent";
+ MarkupElement - (30:1,0 [57] x:\dir\subdir\Test\TestComponent.cshtml) - div
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - myvalue=" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+ IntermediateToken - (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - =" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value,
+ IntermediateToken - - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlContent - (87:1,57 [2] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (87:1,57 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n
+ CSharpCode - (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentValue { get; set; } = "hi";\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..2e114c69c0
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentDesignTimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt
@@ -0,0 +1,24 @@
+Source Location: (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+| var x = "anotherevent"; |
+Generated Location: (854:24,2 [25] )
+| var x = "anotherevent"; |
+
+Source Location: (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml)
+|ParentValue|
+Generated Location: (1098:32,19 [11] )
+|ParentValue|
+
+Source Location: (82:1,52 [1] x:\dir\subdir\Test\TestComponent.cshtml)
+|x|
+Generated Location: (1299:40,52 [1] )
+|x|
+
+Source Location: (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ public string ParentValue { get; set; } = "hi";
+|
+Generated Location: (1619:50,7 [55] )
+|
+ public string ParentValue { get; set; } = "hi";
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..045b8bd4db
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.codegen.cs
@@ -0,0 +1,56 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public partial class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
+ {
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ var x = "anotherevent";
+
+#line default
+#line hidden
+#nullable disable
+ __builder.OpenElement(0, "div");
+ __builder.AddAttribute(1, "myvalue", Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ ParentValue
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ __builder.AddAttribute(2,
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ x.ToString()
+
+#line default
+#line hidden
+#nullable disable
+ , Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value, ParentValue));
+ __builder.SetUpdatesAttributeName("myvalue");
+ __builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ public string ParentValue { get; set; } = "hi";
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..26063fac5d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.ir.txt
@@ -0,0 +1,24 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public partial - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ CSharpCode - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var x = "anotherevent";
+ MarkupElement - (30:1,0 [70] x:\dir\subdir\Test\TestComponent.cshtml) - div
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - myvalue=" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+ IntermediateToken - (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - =" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value,
+ IntermediateToken - - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ CSharpCode - (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentValue { get; set; } = "hi";\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..40c7108b28
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExplicitExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+| var x = "anotherevent"; |
+Generated Location: (586:17,2 [25] )
+| var x = "anotherevent"; |
+
+Source Location: (109:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ public string ParentValue { get; set; } = "hi";
+|
+Generated Location: (1575:47,7 [55] )
+|
+ public string ParentValue { get; set; } = "hi";
+|
+
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs
new file mode 100644
index 0000000000..8ccdb1a97d
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.codegen.cs
@@ -0,0 +1,56 @@
+//
+#pragma warning disable 1591
+namespace Test
+{
+ #line hidden
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Components;
+ public partial class TestComponent : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ #pragma warning disable 1998
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
+ {
+#nullable restore
+#line 1 "x:\dir\subdir\Test\TestComponent.cshtml"
+ var x = "anotherevent";
+
+#line default
+#line hidden
+#nullable disable
+ __builder.OpenElement(0, "div");
+ __builder.AddAttribute(1, "myvalue", Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ ParentValue
+
+#line default
+#line hidden
+#nullable disable
+ ));
+ __builder.AddAttribute(2,
+#nullable restore
+#line 2 "x:\dir\subdir\Test\TestComponent.cshtml"
+ x
+
+#line default
+#line hidden
+#nullable disable
+ , Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value, ParentValue));
+ __builder.SetUpdatesAttributeName("myvalue");
+ __builder.CloseElement();
+ }
+ #pragma warning restore 1998
+#nullable restore
+#line 3 "x:\dir\subdir\Test\TestComponent.cshtml"
+
+ public string ParentValue { get; set; } = "hi";
+
+#line default
+#line hidden
+#nullable disable
+ }
+}
+#pragma warning restore 1591
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt
new file mode 100644
index 0000000000..bbad89af49
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.ir.txt
@@ -0,0 +1,24 @@
+Document -
+ NamespaceDeclaration - - Test
+ UsingDirective - (3:1,1 [14] ) - System
+ UsingDirective - (18:2,1 [34] ) - System.Collections.Generic
+ UsingDirective - (53:3,1 [19] ) - System.Linq
+ UsingDirective - (73:4,1 [30] ) - System.Threading.Tasks
+ UsingDirective - (104:5,1 [39] ) - Microsoft.AspNetCore.Components
+ ClassDeclaration - - public partial - TestComponent - Microsoft.AspNetCore.Components.ComponentBase -
+ MethodDeclaration - - protected override - void - BuildRenderTree
+ CSharpCode - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - var x = "anotherevent";
+ MarkupElement - (30:1,0 [57] x:\dir\subdir\Test\TestComponent.cshtml) - div
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - myvalue=" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.BindConverter.FormatValue(
+ IntermediateToken - (49:1,19 [11] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ HtmlAttribute - (48:1,18 [12] x:\dir\subdir\Test\TestComponent.cshtml) - =" - "
+ CSharpExpressionAttributeValue - -
+ IntermediateToken - - CSharp - Microsoft.AspNetCore.Components.EventCallback.Factory.CreateBinder(this, __value => ParentValue = __value,
+ IntermediateToken - - CSharp - ParentValue
+ IntermediateToken - - CSharp - )
+ CSharpCode - (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+ IntermediateToken - (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n public string ParentValue { get; set; } = "hi";\n
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt
new file mode 100644
index 0000000000..db23e28959
--- /dev/null
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/ComponentRuntimeCodeGenerationTest/BindToElement_WithEventAsExpression/TestComponent.mappings.txt
@@ -0,0 +1,14 @@
+Source Location: (2:0,2 [25] x:\dir\subdir\Test\TestComponent.cshtml)
+| var x = "anotherevent"; |
+Generated Location: (586:17,2 [25] )
+| var x = "anotherevent"; |
+
+Source Location: (96:2,7 [55] x:\dir\subdir\Test\TestComponent.cshtml)
+|
+ public string ParentValue { get; set; } = "hi";
+|
+Generated Location: (1563:47,7 [55] )
+|
+ public string ParentValue { get; set; } = "hi";
+|
+
diff --git a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets
index 540fab290d..c512c7ee49 100644
--- a/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets
+++ b/src/Razor/Microsoft.NET.Sdk.Razor/src/build/netstandard2.0/Microsoft.NET.Sdk.Razor.Compilation.targets
@@ -111,12 +111,6 @@ Copyright (c) .NET Foundation. All rights reserved.
true
-
- 7.3
- $(MaxSupportedLangVersion)
-
-