From 45544858a3ef2109dd2b96f5b4e0cb0a8d29c6fd Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 5 Jul 2018 08:26:46 -0700 Subject: [PATCH] Fix #954 - use weak typing for 'event handlers' This change introduces a mechanism for bypassing type checking and then uses for the 'event handlers'. The event handler tag helpers have some ideosyncratic behaviors and rely on overloading at the render tree builder level. --- .../BlazorDesignTimeNodeWriter.cs | 6 +-- .../BlazorMetadata.cs | 4 +- .../BlazorRuntimeNodeWriter.cs | 6 +-- ...EventHandlerTagHelperDescriptorProvider.cs | 6 ++- ...elperBoundAttributeDescriptorExtensions.cs | 15 +++++- .../DesignTimeCodeGenerationTest.cs | 34 +++++++++++++ .../RuntimeCodeGenerationTest.cs | 36 +++++++++++++- .../TestComponent.codegen.cs | 49 +++++++++++++++++++ .../TestComponent.ir.txt | 34 +++++++++++++ .../TestComponent.mappings.txt | 19 +++++++ .../TestComponent.codegen.cs | 31 ++++++++++++ .../TestComponent.ir.txt | 20 ++++++++ .../TestComponent.mappings.txt | 9 ++++ ...tHandlerTagHelperDescriptorProviderTest.cs | 8 ++- 14 files changed, 265 insertions(+), 12 deletions(-) create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt create mode 100644 test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorDesignTimeNodeWriter.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorDesignTimeNodeWriter.cs index d067eebc63..3ed8d0959c 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorDesignTimeNodeWriter.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorDesignTimeNodeWriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -422,7 +422,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor context.CodeWriter.Write(" = "); // If we have a parameter type, then add a type check. - if (node.BoundAttribute != null) + if (node.BoundAttribute != null && !node.BoundAttribute.IsWeaklyTyped()) { context.CodeWriter.Write(BlazorApi.RuntimeHelpers.TypeCheck); context.CodeWriter.Write("<"); @@ -436,7 +436,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor WriteCSharpToken(context, tokens[i]); } - if (node.BoundAttribute != null) + if (node.BoundAttribute != null && !node.BoundAttribute.IsWeaklyTyped()) { context.CodeWriter.Write(")"); } diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorMetadata.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorMetadata.cs index 95f2cb52b4..673ae9f504 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorMetadata.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorMetadata.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. namespace Microsoft.AspNetCore.Blazor.Razor @@ -30,6 +30,8 @@ namespace Microsoft.AspNetCore.Blazor.Razor { public static readonly string DelegateSignatureKey = "Blazor.DelegateSignature"; + public static readonly string WeaklyTypedKey = "Blazor.IsWeaklyTyped"; + public static readonly string RuntimeName = "Blazor.IComponent"; public readonly static string TagHelperKind = "Blazor.Component"; diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs index b91431ad1b..547d763cc0 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorRuntimeNodeWriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -379,7 +379,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor } else { - if (node.BoundAttribute != null) + if (node.BoundAttribute != null && !node.BoundAttribute.IsWeaklyTyped()) { context.CodeWriter.Write(BlazorApi.RuntimeHelpers.TypeCheck); context.CodeWriter.Write("<"); @@ -393,7 +393,7 @@ namespace Microsoft.AspNetCore.Blazor.Razor context.CodeWriter.Write(tokens[i].Content); } - if (node.BoundAttribute != null) + if (node.BoundAttribute != null && !node.BoundAttribute.IsWeaklyTyped()) { context.CodeWriter.Write(")"); } diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/EventHandlerTagHelperDescriptorProvider.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/EventHandlerTagHelperDescriptorProvider.cs index 457d31465e..ccb307d677 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/EventHandlerTagHelperDescriptorProvider.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/EventHandlerTagHelperDescriptorProvider.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -143,6 +143,10 @@ namespace Microsoft.AspNetCore.Blazor.Razor // Use a string here so that we get HTML context by default. a.TypeName = typeof(string).FullName; + // But make this weakly typed (don't type check) - delegates have their own type-checking + // logic that we don't want to interfere with. + a.Metadata.Add(BlazorMetadata.Component.WeaklyTypedKey, bool.TrueString); + // WTE has a bug 15.7p1 where a Tag Helper without a display-name that looks like // a C# property will crash trying to create the toolips. a.SetPropertyName(entry.Attribute); diff --git a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/TagHelperBoundAttributeDescriptorExtensions.cs b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/TagHelperBoundAttributeDescriptorExtensions.cs index 504eb0d04e..59cf7e1880 100644 --- a/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/TagHelperBoundAttributeDescriptorExtensions.cs +++ b/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/TagHelperBoundAttributeDescriptorExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -20,5 +20,18 @@ namespace Microsoft.AspNetCore.Blazor.Razor attribute.Metadata.TryGetValue(key, out var value) && string.Equals(value, bool.TrueString); } + + public static bool IsWeaklyTyped(this BoundAttributeDescriptor attribute) + { + if (attribute == null) + { + throw new ArgumentNullException(nameof(attribute)); + } + + var key = BlazorMetadata.Component.WeaklyTypedKey; + return + attribute.Metadata.TryGetValue(key, out var value) && + string.Equals(value, bool.TrueString); + } } } diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs index 2832cb83e5..facfb1abdf 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/DesignTimeCodeGenerationTest.cs @@ -174,6 +174,40 @@ namespace Test CompileToAssembly(generated); } + // Regression test for #954 - we need to allow arbitrary event handler + // attributes with weak typing. + [Fact] + public void ChildComponent_WithWeaklyTypeEventHandler() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Blazor; +using Microsoft.AspNetCore.Blazor.Components; + +namespace Test +{ + public class DynamicElement : BlazorComponent + { + } +} +")); + + // Act + var generated = CompileToCSharp(@" +@addTagHelper *, TestAssembly + + +@functions { + private Action OnClick { get; set; } +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [Fact] public void ChildComponent_WithExplicitEventHandler() { diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs index d57e1bcb91..b381d87d7c 100644 --- a/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/RuntimeCodeGenerationTest.cs @@ -166,6 +166,40 @@ namespace Test CompileToAssembly(generated); } + // Regression test for #954 - we need to allow arbitrary event handler + // attributes with weak typing. + [Fact] + public void ChildComponent_WithWeaklyTypeEventHandler() + { + // Arrange + AdditionalSyntaxTrees.Add(Parse(@" +using System; +using Microsoft.AspNetCore.Blazor; +using Microsoft.AspNetCore.Blazor.Components; + +namespace Test +{ + public class DynamicElement : BlazorComponent + { + } +} +")); + + // Act + var generated = CompileToCSharp(@" +@addTagHelper *, TestAssembly + + +@functions { + private Action OnClick { get; set; } +}"); + + // Assert + AssertDocumentNodeMatchesBaseline(generated.CodeDocument); + AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); + CompileToAssembly(generated); + } + [Fact] public void ChildComponent_WithExplicitEventHandler() { @@ -759,8 +793,6 @@ Welcome to your new app. [Fact] // https://github.com/aspnet/Blazor/issues/773 public void Regression_773() { - GenerateBaselines = true; - // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs new file mode 100644 index 0000000000..64eaf8d5aa --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs @@ -0,0 +1,49 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Blazor; + using Microsoft.AspNetCore.Blazor.Components; + public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent + { + #pragma warning disable 219 + private void __RazorDirectiveTokenHelpers__() { + ((System.Action)(() => { +global::System.Object __typeHelper = "*, TestAssembly"; + } + ))(); + } + #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.Blazor.RenderTree.RenderTreeBuilder builder) + { + base.BuildRenderTree(builder); + __o = Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue( +#line 2 "x:\dir\subdir\Test\TestComponent.cshtml" + OnClick + +#line default +#line hidden + ); + builder.AddAttribute(-1, "ChildContent", (Microsoft.AspNetCore.Blazor.RenderFragment)((builder2) => { + } + )); + } + #pragma warning restore 1998 +#line 4 "x:\dir\subdir\Test\TestComponent.cshtml" + + private Action OnClick { get; set; } + +#line default +#line hidden + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt new file mode 100644 index 0000000000..604f3fa88e --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt @@ -0,0 +1,34 @@ +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 [33] ) - Microsoft.AspNetCore.Blazor + UsingDirective - (140:6,1 [44] ) - Microsoft.AspNetCore.Blazor.Components + ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent - + DesignTimeDirective - + DirectiveToken - (14:0,14 [32] ) - "*, Microsoft.AspNetCore.Blazor" + DirectiveToken - (14:0,14 [9] ) - "*, Test" + DirectiveToken - (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) - *, TestAssembly + 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 - + IntermediateToken - - CSharp - base.BuildRenderTree(builder); + HtmlContent - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (29:0,29 [2] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n + ComponentExtensionNode - (31:1,0 [37] x:\dir\subdir\Test\TestComponent.cshtml) - DynamicElement - Test.DynamicElement + ComponentAttributeExtensionNode - (56:1,25 [8] x:\dir\subdir\Test\TestComponent.cshtml) - onclick - onclick + CSharpExpression - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue( + IntermediateToken - (57:1,26 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - OnClick + IntermediateToken - - CSharp - ) + HtmlContent - (68:1,37 [4] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (68:1,37 [4] x:\dir\subdir\Test\TestComponent.cshtml) - Html - \n\n + CSharpCode - (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Action OnClick { get; set; }\n diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt new file mode 100644 index 0000000000..ecad042f3e --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/DesignTimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt @@ -0,0 +1,19 @@ +Source Location: (14:0,14 [15] x:\dir\subdir\Test\TestComponent.cshtml) +|*, TestAssembly| +Generated Location: (559:16,38 [15] ) +|*, TestAssembly| + +Source Location: (57:1,26 [7] x:\dir\subdir\Test\TestComponent.cshtml) +|OnClick| +Generated Location: (1201:30,26 [7] ) +|OnClick| + +Source Location: (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) +| + private Action OnClick { get; set; } +| +Generated Location: (1516:41,12 [62] ) +| + private Action OnClick { get; set; } +| + diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs new file mode 100644 index 0000000000..5ec08178e3 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.codegen.cs @@ -0,0 +1,31 @@ +// +#pragma warning disable 1591 +namespace Test +{ + #line hidden + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.AspNetCore.Blazor; + using Microsoft.AspNetCore.Blazor.Components; + public class TestComponent : Microsoft.AspNetCore.Blazor.Components.BlazorComponent + { + #pragma warning disable 1998 + protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder) + { + base.BuildRenderTree(builder); + builder.OpenComponent(0); + builder.AddAttribute(1, "onclick", Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue(OnClick)); + builder.CloseComponent(); + } + #pragma warning restore 1998 +#line 4 "x:\dir\subdir\Test\TestComponent.cshtml" + + private Action OnClick { get; set; } + +#line default +#line hidden + } +} +#pragma warning restore 1591 diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt new file mode 100644 index 0000000000..b432de290d --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.ir.txt @@ -0,0 +1,20 @@ +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 [35] ) - Microsoft.AspNetCore.Blazor + UsingDirective - (140:6,1 [46] ) - Microsoft.AspNetCore.Blazor.Components + ClassDeclaration - - public - TestComponent - Microsoft.AspNetCore.Blazor.Components.BlazorComponent - + MethodDeclaration - - protected override - void - BuildRenderTree + CSharpCode - + IntermediateToken - - CSharp - base.BuildRenderTree(builder); + ComponentExtensionNode - (31:1,0 [37] x:\dir\subdir\Test\TestComponent.cshtml) - DynamicElement - Test.DynamicElement + ComponentAttributeExtensionNode - (56:1,25 [8] x:\dir\subdir\Test\TestComponent.cshtml) - onclick - onclick + CSharpExpression - + IntermediateToken - - CSharp - Microsoft.AspNetCore.Blazor.Components.BindMethods.GetEventHandlerValue( + IntermediateToken - (57:1,26 [7] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - OnClick + IntermediateToken - - CSharp - ) + CSharpCode - (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) + IntermediateToken - (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) - CSharp - \n private Action OnClick { get; set; }\n diff --git a/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt new file mode 100644 index 0000000000..4d99283766 --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.Build.Test/TestFiles/RuntimeCodeGenerationTest/ChildComponent_WithWeaklyTypeEventHandler/TestComponent.mappings.txt @@ -0,0 +1,9 @@ +Source Location: (84:3,12 [62] x:\dir\subdir\Test\TestComponent.cshtml) +| + private Action OnClick { get; set; } +| +Generated Location: (989:23,12 [62] ) +| + private Action OnClick { get; set; } +| + diff --git a/test/Microsoft.AspNetCore.Blazor.Razor.Extensions.Test/EventHandlerTagHelperDescriptorProviderTest.cs b/test/Microsoft.AspNetCore.Blazor.Razor.Extensions.Test/EventHandlerTagHelperDescriptorProviderTest.cs index 8cf1910ae9..5f6d7959ad 100644 --- a/test/Microsoft.AspNetCore.Blazor.Razor.Extensions.Test/EventHandlerTagHelperDescriptorProviderTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Razor.Extensions.Test/EventHandlerTagHelperDescriptorProviderTest.cs @@ -1,6 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.CSharp; @@ -97,6 +98,11 @@ namespace Test Assert.False(attribute.IsIndexerBooleanProperty); Assert.False(attribute.IsIndexerStringProperty); + Assert.Collection( + attribute.Metadata.OrderBy(kvp => kvp.Key), + kvp => Assert.Equal(kvp, new KeyValuePair(BlazorMetadata.Component.WeaklyTypedKey, bool.TrueString)), + kvp => Assert.Equal(kvp, new KeyValuePair("Common.PropertyName", "onclick"))); + Assert.Equal( "Sets the 'onclick' attribute to the provided string or delegate value. " + "A delegate value should be of type 'System.Action'.",