Search code examples
c#asp.net-coretag-helpersasp.net-core-tag-helpers

Razor Tag Helper - Binding to a Collection


Using ASP.NET Core 2.2 I am trying to build a Tag Helper that will bind to a ModelExpression representing a collection of SelectListItems. I then want to be able to access and iterate over the SelectListItems contained in the list.

In code terms, it looks something like this...

[HtmlTargetElement("check-box-list", Attributes = "asp-for)]
public class CheckboxListTagHelper : TagHelper
{
    // Where the model is an IEnumerable<SelectItemList>
    [HtmlAttributeName("asp-for")]
    public ModelExpression AspFor { get; set; }

    public override async Task ProcessAsync(
        TagHelperContext context, TagHelperOutput output)
    {
        // I want to be able to reference the IEnumerable<SelectListItem>
        // represented by the model
        var modelItems = AspFor.Model as IEnumerable<SelectListItem>; // WRONG!
        ...
    }
}

I assume I need to use the ModelExpression.MetaData or the ModelExpression.ModelExpolorer properties, but I can't find any information that points me in the right direction.

An inelegant fix has been to supply the same model as an additional property:

[HtmlAttributeName("select-item-list")]
public IEnumerable<SelectListItem> SelectItemList { get; set; }

But this looks messy in the view:

<check-box-list
    asp-for="SelectedAuthorityLevels"
    checkbox-list="Model.SelectedAuthorityLevels" />

as you are binding to the same model property twice.

Any guidance would be much appreciated.


Solution

  • The answer was, in the end, very easy - since I know the expression type, I can simply cast it as follows:

    var selectList = AspFor.Model as IEnumerable<SelectListItem>;
    
    if (selectList == null) {
       var msg = "CheckboxList tag helper attribute 'asp-for' must of type " +
          "IEnumerable<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>!";
       throw new Exception(msg);
    }