The tag helper 'input' must not have C# in the element's attribute declaration area
Asked Answered
P

7

33

We are experiencing the following error when build ASP.NET Core MVC application which is recently migrated from .NET Core 2.2 to 3.0:

The tag helper 'input' (or 'textarea' or any other) must not have C# in the element's attribute declaration area.

We used Razor @functions to return HTML attribute content in order to overcome that issue but it looks ugly when you use variable for returning it from function without any extra logic (function dummy(htmlAttributeContent) return htmlAttributeContent)

@{
    var roAttrHTML = "";
    if (!user.GotAccessToken("someToken")) {
        roAttrHTML = " readonly=\"readonly\" ";
    }
}
<textarea class="testClass" asp-for="testId" @readonlyAttribute>@Model.Id</textarea>

Actually we got error

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

when compile our ASP.NET Core MVC application whereas we need to get approach (better without @functions usage) which will provide us a way to overcome that issue (as we have plenty of pages with similar logic which we need to touch once and avoid any possible problems with presumable new changes in support of attributes in the future .NET Core versions)

Pokpoke answered 12/11, 2019 at 9:36 Comment(3)
How did you define @readonlyAttribute?I could also get the same error in asp.net core 2.2.Why not try readonly=@readonlyAttribute?Grandmotherly
@Grandmotherly that should be the accepted answer!Ulita
@Ulita actually, that does nothing, because it doesn't matter what value there is for readonly attribute, once it's there, the field is readonlyCollaboration
T
33

If you don't need to use the TagHelper, you can use <!elementName> to disable it for a specific element:

<!textarea class="testClass" asp-for="testId" @readonlyAttribute>@Model.Id</!textarea>

See @glenn223's answer for a more structural solution. I made an improved version of his solution, by adding support for anonymous objects:

using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace  {YourBaseNameSpace}.Helpers.TagHelpers
{
    [HtmlTargetElement(Attributes = "custom-attributes")]
    public class CustomAttributesTagHelper : TagHelper
    {
        public object CustomAttributes { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var customAttributesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(CustomAttributes);
            foreach (var (key, value) in customAttributesDictionary)
            {
                output.Attributes.SetAttribute(key, value);
            }
        }
    }
}
Tideway answered 28/4, 2021 at 13:5 Comment(0)
L
26

According to the docs, you can do it this way, in ASP .NET 5.0

<input asp-for="LastName" 
       disabled="@(Model?.LicenseId == null)" />

https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-5.0#c-in-tag-helpers-attributedeclaration

Lati answered 4/11, 2021 at 21:14 Comment(0)
C
12

You can do it like this:

@if (!user.GotAccessToken("someToken")) 
{
   <textarea class="testClass" asp-for="testId" readonly>@Model.Id</textarea>
}
else
{
   <textarea class="testClass" asp-for="testId">@Model.Id</textarea>
}
Collaboration answered 1/5, 2021 at 10:31 Comment(0)
A
7

I got the same problem, but i got an easy solution:

Code that throws the error:

<select asp-for="Journeys.VehicleType" class="test" style="width: 100%;" id="vehicleType" @disabled>

Code that works:

<select @disabled asp-for="Journeys.VehicleType" class="test" style="width: 100%;" id="vehicleType">

All i did to make my IDE doesnt throw the error is moving the @disabled attribute infront of the "asp-for" attribute.

Also works for normal input fields:

Code that throws the error:

<input  type="datetime-local" asp-for="Journeys.StartTime" @disabled id="startTime"/>

Code that works:

 <input @disabled type="datetime-local" asp-for="Journeys.StartTime" id="startTime"/>

Info: @disabled is just a variable which contains empty string or "disabled":

var disabled = "";   
if (Model.Disabled)
{
    disabled = "disabled";       
}

Hope this will help some people with the same problem.

Ardisardisj answered 17/12, 2021 at 10:33 Comment(1)
I upvoted this before realizing it broke bindings. The solution @Lati posted worked.Journalist
H
4

I encountered this same problem, when creating a new 3.0 application. An old 2.2 application allowed me to have C# in the declaration even though "it's not valid"1.

What I did was author my own TagHelper2, using the below steps:

  1. Create file: CustomAttributeTagHelper .cs
namespace {YourBaseNameSpace}.Helpers.TagHelpers
{
    using System.Collections.Generic;
    using Microsoft.AspNetCore.Razor.TagHelpers;

    [HtmlTargetElement(Attributes = "custom-attributes")]
    public class CustomAttributeTagHelper : TagHelper
    {
        public Dictionary<string, string> CustomAttributes { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (CustomAttributes != null)
                foreach (var pair in CustomAttributes)
                    if (!output.Attributes.ContainsName(pair.Key))
                        output.Attributes.Add(pair.Key, pair.Value);
        }
    }
}
  1. Modify: /Pages/Shared/_ViewImports.cshtml, adding the below line below Microsoft's own @addTagHelper
@addTagHelper {YourBaseNameSpace}.Helpers.TagHelpers.*, {Your Assembly Name}

KEY POINT: ensure you use the assembly name and not the namespace after the comma above

2a. If you're not sure what your assembly name is then run the below code in your Program => Main(string[] args) method:

Type t = typeof({YourBaseNameSpace}.Helpers.TagHelpers.CustomAttributeTagHelper);
string s = t.Assembly.GetName().Name.ToString();
Console.WriteLine($"The fully qualified assembly name you need is: {s}.");
  1. You then use it as simply as this in a razor page:
@{
    Dictionary<string, string> myCustomAttributes = new Dictionary<string, string> {
        ["data-first-custom-attribute"] = "my custom value"
    };

    if (!user.GotAccessToken("someToken")) {
        myCustomAttributes.Add("readonly","readonly");
    }
}

<input custom-attributes="myCustomAttributes" />

NOTE: This code can be used on any TagHelper and means you can add any custom attributes you like.

If you wanted to make it for just a single attribute (like your readonly above) then you can create a conditional TagHelper that requires a bool on construction or as it's value.

Haaf answered 3/1, 2020 at 13:41 Comment(2)
What a pain in the ass.Tercel
This is a great solution for this problem. The class can be improved by adding support for specifying the attributes via anonymous objects, using HtmlHelper.AnonymousObjectToHtmlAttributes(CustomAttributes);Tideway
M
1

For the same issue but with multiple attributes I did following workaround:

@{
    //...
    string attributes = "...prepare attributes ...";
    string tag = "<input " + attributes + " />";
    <text>@Html.Raw(tag)</text>
    //...
}

@Html.Raw is not recommended because of some security vulnerabilities, but I still used it here. Be aware of that risk. If needed I can share some additional articles about that risk. Otherwise, for a single attribute I agree with @Rena's comment.

Malvie answered 5/11, 2020 at 19:31 Comment(0)
V
1

I ended up removing the line

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 

from _ViewImports.cshtml

In my case I had to construct the html with great precision and I did not use the the TagHelpers anyway.

Vestal answered 13/12, 2020 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.