aspnet / RazorTooling

Razor tooling for Visual Studio 2015

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TagHelper with no end tag: parsing issues

NoneGiven opened this issue · comments

Create a TagHelper with WithoutEndTag structure:

[HtmlTargetElement("msg-helper", TagStructure = TagStructure.WithoutEndTag)]
public class MsgHelperTagHelper : TagHelper {
    public string Msg { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output) {
        output.TagName = "";
        output.Content.SetContent("<div>" + Msg + "</div>");
    }
}

Create a Razor view that uses it inside a C# if block:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Asdf</title>
    </head>
    <body>
        @if (1 + 2 == 3) {
            <msg-helper msg="Hello">
        }
        else {
            <div>Hi</div>
        }
    </body>
</html>

Razor reports two incorrect errors, the first one on the tag helper element:
The "msg-helper" element was not closed. All elements must either be self-closing or have a matching end tag.

And the second on the closing tag:
Encountered end tag "html" with no matching start tag. Are your start/end tags properly balanced?

Moving the tag helper outside the if/else blocks in the same markup makes the errors disappear.

I believe this is failing at the parser stage, which is well before any tag helpers happen.

I believe this issue happens because Razor doesn't know where the tag starts and ends - it doesn't know about tag helpers.

You need to wrap the <msg-helper .... > tag in the <text> ... </text> pseudo-tag to tell Razor where the HTML begins and ends.

        @if (1 + 2 == 3) {
            <text>
            <msg-helper msg="Hello">
             </text>
       }
        else {
            <div>Hi</div>
        }

The Razor parser knows just a bit about HTML, and just a bit about C#, so you sometimes have to give it hints about where things start and end.

@NTaylorMullen @DamianEdwards can you confirm if my statement is all there is to it?

You can just make the element self-closing (like the error message says):

@if (1 + 2 == 3) {
            <msg-helper msg="Hello" />
       }
        else {
            <div>Hi</div>
        }