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

2

8

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)
Critta answered 30/3, 2016 at 8:15 Comment(1)
I'm thinking your solution here is to not exclude that 'asp-route-dateNext' totally but rather be able to pass a nullable DateTime/empty string or something which can be handled in the controller. It doesn't really make sense to have a conditional on that property in the form tag but rather handle on the controller. Is there specific there any reason for this?Clubfoot
E
11

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.

Entente answered 30/3, 2016 at 8:54 Comment(2)
Setting an attribute to null will make stop it from being rendered in the HtmlLuteolin
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.Agha
I
6

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.

Instrumentalism answered 8/6, 2020 at 12:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.