Mvc: adding TagHelpers breaks existing <select> elements with Razor in the option tags

Created on 10 Dec 2015  路  9Comments  路  Source: aspnet/Mvc

if I add @addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"

existing <select> elements like this:

<select>
  @foreach (var item in MyList)
  {
    <option value="@item.Value" @if (item.Value == Model.ToString()) { <text> selected="selected" </text> }>@item.Key</option>
  }
</select>

That have inline razor code throw an error "the tag helper 'option' must not have C# in the element's attribute declaration area.

Why does it assume the option is a taghelper? Is there a way to override this?

sorry about the code formatting, could not figure out how to make github format this...

Most helpful comment

I went with this option, which doesn't get highlighted as invalid in VS.

<select class="form-control">
      <option value="-1">None</option>
      @foreach (var item in Html.GetEnumSelectList<MyEnum>())
      {

           @: <option value="@item.Value" @(item.Selected ? "selected" : "") >@item.Text</option>
       }
</select>

All 9 comments

Yup, this is by design. We currently have an issue over in Razor tracking this: https://github.com/aspnet/Razor/issues/96.

As a workaround I'd recommend doing the following for your option tag:

<option value="@item.Value" selected="@(item.Value == Model.ToString())">@item.Key</option>

Another option is to use <!option ...>...</!option> to ensure Razor does not associate the element with a tag helper.

FYI I reformatted your example.

ok, thanks, yeah the <!option ..> was what I was looking for, I know I can rework these, but I have a lot of legacy code that I ported over from MVC 5 so that will be a lot easier for now.

does not seem to work inside foreach loops.

@rickythefox could you provide more detail on what doesn't work w/ <!option> w/in a foreach?

Sure! The code below does not compile in a Razor view (trivial example, will set all options to selected):

<select class="form-control">
    <option value="-1">None</option>
    @foreach (var item in Html.GetEnumSelectList<MyEnum>())
    {
        var selected = " selected";
        <!option value="@item.Value" @selected >@item.Text</!option>
    }
</select>

@rickythefox since you're doing everything manually, you must set selected to string.Empty in at least some cases.

Details

Your code _explicitly_ sets the selected attribute for all generated <option>s. Tag helpers are not doing anything in this example: The SelectTagHelper matches the <select> element but no-ops. And, the OptionTagHelper matches (just) the first <option> element but also no-ops. (The earlier problem was the OptionTagHelper matched all <option> elements but tag helpers do not support @selected and similar attribute name / value expansions.)

@dougbu my bad, the code is marked as invalid by VS so I assumed it would not compile. In reality the selectedvar gets its value from somewhere, this is just a trivial example so i hardcoded it to a string. :)

image

I went with this option, which doesn't get highlighted as invalid in VS.

<select class="form-control">
      <option value="-1">None</option>
      @foreach (var item in Html.GetEnumSelectList<MyEnum>())
      {

           @: <option value="@item.Value" @(item.Selected ? "selected" : "") >@item.Text</option>
       }
</select>
Was this page helpful?
0 / 5 - 0 ratings