If a tag in a Razor page does not match with a Razor Component, but component binding syntax is added, the compiler reports a binding error. I
Steps to reproduce the behavior:
<BadComponent /> in the HTML (this should colour blue as if a HTML tag) <BadComponent /> is treated as HTML and rendered normally.<BadComponent bind-Value="@Test" />Error: The attribute names could not be inferred from bind attribute 'bind-Value'. Bind attributes should be of the form'bind', 'bind-value' or 'bind-value-change'
This leads the user to believe they have a binding issue, when in fact it's the component that does not exist.
Would expect the compiler to report that it was not able to resolve BadComponent as a Razor component
Microsoft Windows [Version 10.0.17763.437]
(c) 2018 Microsoft Corporation. All rights reserved.
.NET Core SDK (reflecting any global.json):
Version: 3.0.100-preview4-011223
Commit: 118dd862c8
Runtime Environment:
OS Name: Windows
OS Version: 10.0.17763
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.0.100-preview4-011223\
Host (useful for support):
Version: 3.0.0-preview4-27615-11
Commit: ee54d4cbd2
.NET Core SDKs installed:
1.0.4 [C:\Program Files\dotnet\sdk]
1.1.0 [C:\Program Files\dotnet\sdk]
2.0.0 [C:\Program Files\dotnet\sdk]
2.0.2 [C:\Program Files\dotnet\sdk]
2.0.3 [C:\Program Files\dotnet\sdk]
2.1.2 [C:\Program Files\dotnet\sdk]
2.1.4 [C:\Program Files\dotnet\sdk]
2.1.102 [C:\Program Files\dotnet\sdk]
2.1.104 [C:\Program Files\dotnet\sdk]
2.1.201 [C:\Program Files\dotnet\sdk]
2.1.202 [C:\Program Files\dotnet\sdk]
2.1.300 [C:\Program Files\dotnet\sdk]
2.1.301 [C:\Program Files\dotnet\sdk]
2.1.302 [C:\Program Files\dotnet\sdk]
2.1.400-preview-009171 [C:\Program Files\dotnet\sdk]
2.1.400 [C:\Program Files\dotnet\sdk]
2.1.401 [C:\Program Files\dotnet\sdk]
2.1.402 [C:\Program Files\dotnet\sdk]
2.1.403 [C:\Program Files\dotnet\sdk]
2.1.500-preview-009335 [C:\Program Files\dotnet\sdk]
2.1.500-preview-009404 [C:\Program Files\dotnet\sdk]
2.1.500 [C:\Program Files\dotnet\sdk]
2.1.502 [C:\Program Files\dotnet\sdk]
2.1.503 [C:\Program Files\dotnet\sdk]
2.1.504 [C:\Program Files\dotnet\sdk]
2.1.505 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009426 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009472 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009497 [C:\Program Files\dotnet\sdk]
2.1.600 [C:\Program Files\dotnet\sdk]
2.1.601 [C:\Program Files\dotnet\sdk]
2.1.602 [C:\Program Files\dotnet\sdk]
2.1.700-preview-009597 [C:\Program Files\dotnet\sdk]
2.1.700-preview-009601 [C:\Program Files\dotnet\sdk]
2.2.103 [C:\Program Files\dotnet\sdk]
3.0.100-preview4-011223 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview4-19216-03 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.3-servicing-26724-03 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.0-preview2-26905-02 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview4-27615-11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0-preview4-27613-28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
@rynowak We've had a lot of people confused about why we can't give errors about <ComponentThatDoesNotExist />. Let's consider making the PascalCaseComponentName convention into in actual enforced rule, with a compiler error if you use that casing on something that resolves as an element not a component.
I'm only saying we should consider this, as we may decide not to be so heavy-handed. If we did it, we would most likely also want some directive that suppresses the rule for the current file (or everywhere, if in _Imports.razor), because it's perfectly legal to write HTML as <Div>...</Div> or <DIV>...</DIV> and some people may have obscure reasons for doing so (e.g., they have to copy-paste in massive blocks of such markup from some other system).
I think it will be a welcome addition for most people.
People also think they can create a Button component and it will be something different than <button> HTML element. Currently I don't have computer with Blazor at hand and I cannot check but probably this problem still exists. Maybe it is a good idea to force PascalCase convention for components and at the same time make some changes to allow component's names which are similar to HTML elements but with different casing.
This is fine by me. This seems more appropriate as a warning rather than an error though. @NTaylorMullen do you have any cool thoughts about how users would suppress this?
I'd imagine something like:
@pragma suppress RZ1337
<Div>#YOLO</Div>
Agree with both @SteveSandersonMS and @rynowak 's suggestions. I'm not exactly new to Blazor and I made these errors very easily, as have others, so helping spot when components are unresolved makes sense.
In reply to @Andrzej-W yes it still exists, I created a <Div /> component with no problems, so it might be a good idea to either warn or raise an error if a component has the same name as a HTML tag?
The list of html tags is know. So if we create a component with the same name, regardless of case, this could be a warning.
If a non-html tag is found in the razor that doesn't resolve to a component, this too could be a warning.
@NTaylorMullen do you have any cool thoughts about how users would suppress this?
In regards to suppressing, I'd stay away from the single line @pragma suppress ... suggestion because it overloads the C# meaning of pragma which adds to the confusion of which portions of a Razor document are impacted when providing those pragmas and the level of support is in regards to C# error/warning codes? i.e:
@* What happens here? *@
@pragma suppress 4507
@pragma suppress RZ1337
...
@functions {
// Do things in here have the suppression?
}
I see three options:
@razor suppress RZ1337. It wouldn't correspond to any sort of C# pragma and it would be smart about applying the pragma logic to underlying directives such as @functions@pragma suppress ComponentNameEnforcement { ... } which could disallow specific concepts inside of them (such as @functions).@strict) where it's opt-in vs. opt-out. It could be added to every _Imports.razor template (we'd make it work in imports) and would still allow other frameworks that operate on pascal cased elements at JS time. I don't understand why we can't just do 1 and call it @pragma. That name is well known unlikely to collide with code in a user's project.
My concern is just with its C# equivalent and any confusion it might introduce. If you feel like those concerns aren't valid then sure we can go with 1 with pragma
Closing this in favor of #9860 - which contains the solution we're going to use for this.
Most helpful comment
@rynowak We've had a lot of people confused about why we can't give errors about
<ComponentThatDoesNotExist />. Let's consider making the PascalCaseComponentName convention into in actual enforced rule, with a compiler error if you use that casing on something that resolves as an element not a component.I'm only saying we should consider this, as we may decide not to be so heavy-handed. If we did it, we would most likely also want some directive that suppresses the rule for the current file (or everywhere, if in
_Imports.razor), because it's perfectly legal to write HTML as<Div>...</Div>or<DIV>...</DIV>and some people may have obscure reasons for doing so (e.g., they have to copy-paste in massive blocks of such markup from some other system).