Mixing C# and HTML Helper tags ASP.NET MVC 6 (ASP.NET Core)

10,389

Solution 1

With Razor, every part of the markup has to be well formed. You cannot have dangling opening tags, or interrupt markup for Razor expresions. So things like this are not valid and as such cause syntax errors:

<!-- Interrupting a tag -->
<div
@if (condition) {
     attribute="bar"
}
>

<!-- Also not possible: Conditionally opening tags -->
if (condition) {
    <span>
}
Some text
if (condition) {
    </span>
}

So you have to make sure that the markup within Razor expressions, basically everything between the curly braces, is a valid expression, and that tags are always complete.

This unfortunately means that you cannot use @if to conditionally add an attribute (regardless of whether that’s a tag helper attribute or not).

If it was just plain HTML, you could make Razor render raw text, which is not interpreted by the Razor parser and as such does not need to be valid markup (so above things would work). However, in raw text, tag helpers also don’t run, so that doesn’t help you here.

This leaves you essentially with three choices now:

  1. Wrap everything in a giant @if and essentially duplicate the whole form tag:

    @if (condition) {
        <form with-that-extra="attribute">
            All the form content
        </form>
    }
    else {
        <form>
            All the form content
        </form>
    }
    

    Of course, this is just terrible since you need to duplicate really the whole form content (otherwise, the tags within the @if wouldn’t be well formed).

  2. Writing your own tag helper which encapsulates the logic behind the @if condition check.

    This works well for more general things, but is a bit tedious just for adding an optional attribute.

  3. Using an expression syntax to pass some “null value” to the route if the condition is not met:

    <form …
        asp-route-dateNext="@(Model.incBalance == 0 ? Model.dataEnd.ToString("yyyy-MM-dd") : null)">
    </form>
    

    This is likely the easiest solution. The default value null there will also prevent the tag helper from running for that attribute, so it’s just as if you omitted it completely.

Solution 2

I am migrating to aspnet core 3.0 from mvc now, and got the same error. since I didn't use any tag helper features, so I just simply remove the taghelper import directive by comment the line in _viewimports by:

@*@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers*@

now the views rendered happily.

Share:
10,389
Kolya_Net
Author by

Kolya_Net

Developer systems in ASP.NET MVC and Core, as well as Xamarin

Updated on June 26, 2022

Comments

  • Kolya_Net
    Kolya_Net almost 2 years

    I'm using the new Helper tags in ASP.NET MVC 6.

        <form asp-area="DAS"
              asp-controller="Report"
              asp-action="Add"
              asp-route-id="@Model.id"
              asp-route-incBalance="@Model.incBalance"
              asp-route-dateSet="@Model.dataStart.ToString("yyyy-MM-dd")"
              asp-route-dateNext="@Model.dataEnd.ToString("yyyy-MM-dd")"
              method="post" role="form">
        </form>
    

    I want to routing attribute:

    asp-route-dateNext="@Model.dataEnd.ToString("yyyy-MM-dd")"
    

    was applied only if:

              {
                  if (Model.incBalance == 0)
                  {
                      asp-route-dateNext="@Model.dataEnd.ToString("yyyy-MM-dd")"
                  }
              }
    

    As a result, I want to get something like this:

        <form asp-area="DAS"
              asp-controller="Report"
              asp-action="Add"
              asp-route-id="@Model.id"
              asp-route-incBalance="@Model.incBalance"
              asp-route-dateSet="@Model.dataStart.ToString("yyyy-MM-dd")"
              {
                 if (Model.incBalance == 0)
                 {
                     asp-route-dateNext="@Model.dataEnd.ToString("yyyy-MM-dd")"
                 }
              }
              method="post" role="form">
        </form>
    

    I get these errors:

    TagHelper attributes must be well-formed.

              if (Model.incBalance == 0)
    

    and

    The tag helper 'form' must not have C# in the element's attribute declaration area.

                  asp-route-dateNext="@Model.dataEnd.ToString("yyyy-MM-dd")"
    

    I'm using Visual Studio 2015 Update 1

    Update 1: I also tried this option:

    @(Model.incBalance == 0 ? "asp-route-dateNext=" + Model.dataEnd.ToString("yyyy-MM-dd") : string.Empty)
    

    But the error remained:

    The tag helper 'form' must not have C# in the element's attribute declaration area.

          @(Model.incBalance == 0 ? "asp-route-dateNext=" + Model.dataEnd.ToString("yyyy-MM-dd") : string.Empty)
    
  • JonTheMon
    JonTheMon about 8 years
    Setting an attribute to null will make stop it from being rendered in the Html
  • Netricity
    Netricity about 4 years
    Option 3 (passing null to output no atttribute at all) is ideal for the HTML5 disabled attribute, which does not otherwise have any on/off value.