In this article, we are going to learn about the select tag helper and its various uses.

We are going to start with a brief overview of what exactly tag helpers in ASP.NET Core are and then proceed to learn more about the select tag helper.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin.

Tag Helpers in ASP.NET Core

Tag helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.

In simpler terms, a tag helper is a server-side component that helps create and render HTML elements in Razor files.

ASP.NET Core provides a variety of built-in tag helpers that are very helpful in creating Razor views and pages.

But before we tackle select tag helper let’s clear one more thing up.

Tag Helpers vs HTML Helpers

Both tag helpers and HTML helpers render HTML elements in Razor files, however, they have their syntactical differences.

Let’s first generate a strongly typed input element using an HTML helper:

<div class="form-group">
    <label for="city">City with HTML Helper</label>
    @Html.TextBoxFor(m => m.City, new {@class="form-control"})
    @Html.ValidationMessageFor(m => m.City, message:"City can't be empty", new {@class="text-danger font-weight-bold"})
</div>

Now, we use an input tag helper to generate the same markup:

<div class="form-group">
    <label for="city">City with Tag Helper</label>
    <input type="text" class="form-control" asp-for="City">
    <span asp-validation-for="City" class="text-danger font-weight-bold"></span>
</div>

Tag helpers provide a more native HTML kind of feel while creating web pages whereas HTML helpers are invoked similarly to methods that are mixed with HTML inside Razor views.

The result is the same, but the syntax is different.

Now that we are aware of tag helpers, let’s learn about the select tag helper in detail. 

Select Tag Helper

select tag helper generates a select element and the associated option elements for the properties of a model.

In simpler terms, it helps to generate a dropdown list for a given model.

We have two very important attributes for a select tag helper:

  • asp-for: It specifies the model property name for the select element
  • asp-items: It specifies the option items

The HTML helper counterpart of a select tag helper is Html.DropDownListFor(x=> x.PropertyName).

Use a List<SelectListItem> to Render a Select Element

Let’s create a ProductViewModel with a string and a List<SelectListItem> properties:

public class ProductViewModel
{
    public string Product { get; set; }
    public List<SelectListItem> Products { get; set; }
}

After that, we create an MVC action method to return a view with an instance of the ProductViewModel:

public IActionResult Index()
{
    var model = new ProductViewModel
    {
        Products = new List<SelectListItem>
        {
            new SelectListItem
            {
                Text = "Motherboards",
                Value = "MB"
            },
            new SelectListItem
            {
                Text = "Graphic Cards",
                Value = "GC"
            },
            new SelectListItem
            {
                Text = "Liquid Coolants",
                Value = "LC"
            }
        },
        Product = "GC"
    };

    return View(model);
}

Finally, we work on the Index view and render a dropdown list with the help of a select tag helper:

@model ProductViewModel
@{
    ViewData["Title"] = "Home Page";
}

<h3>Products Dropdown List</h3>
<form method="post">
    <select class="form-select-sm" asp-for="Product" asp-items="@Model.Products"></select>
    <div class="mt-4">
        <input class="btn btn-primary" type="submit" value="Submit"/>
    </div>
</form>

The asp-for attribute is bound to the string Product property while the asp-items attribute is bound to the list of SelectListItems

SelectListItem is a class that resides in Microsoft.AspNetCore.Mvc.Rendering namespace.

Let’s debug the project and browse the Index view:

dropdown

Graphic Cards is by default selected in the dropdown because we have set Product = "GC" in the code.

We can inspect the dropdown element to find further details:

product dropdown inspect element

asp-for="Product" renders both the id and name attributes as Product, the name attribute helps in sending the selected dropdown value to the POST action method when we submit the form.

Now, we can create a post-action method:

[HttpPost]
public IActionResult Index(ProductViewModel model)
{
    var selectedProduct = model.Product;

    return Content("The selected value: " + selectedProduct);
}

The selected value of the products dropdown transfers from the view to the controller via the Product property.

Now that we have seen the usage of SelectListItem, let’s explore how we can render a select tag helper using different mechanisms.

Use a List<ComplexViewModel> to Render a Select Element

Let’s create an EmployeeViewModel with an Id and EmployeeName properties:

public class EmployeeViewModel
{
    public int Id { get; set; }
    public string EmployeeName { get; set; }
}

We can create a static method to return a few dummy entries:

public static List<EmployeeViewModel> GetEmployees()
{
    return new List<EmployeeViewModel>
    {
        new EmployeeViewModel
        {
            Id = 101,
            EmployeeName = "Mark"
        },
        new EmployeeViewModel
        {
            Id = 102,
            EmployeeName = "Dave"
        },
        new EmployeeViewModel
        {
            Id = 103,
            EmployeeName = "Rosy"
        }
    };
}

Now, we create an action method to return a view with these dummy employees:

public IActionResult SelectTagHelperWithComplexViewModel()
{
    var model = new SelectViewModel
    {
        Employees = StaticRepository.GetEmployees()
    };

    return View(model);
}

And a dropdown list using the select tag helper:

@model SelectViewModel
@{
    ViewData["Title"] = "Employee Dropdown";
}

<h3 class="mt-2">Employees Dropdown - Using a List of Complex Models</h3>

<select class="form-select-sm" asp-for="SelectedEmployeeId"
        asp-items="new SelectList(@Model.Employees, nameof(EmployeeViewModel.Id),
                   nameof(EmployeeViewModel.EmployeeName))">
    <option>Please Select</option>
</select>

In this case, we can’t directly use the @Model.Employees property with the asp-items attribute, because we are using a complex class EmployeeViewModel.

We need to tweak the approach and create a SelectList object on the fly:

public SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue);

Use a Static List to Render a Select Element

Let’s create a list of  countries:

public static List<string> GetCountries()
{
    return new List<string>
    {
        "India","USA","UK","France","Germany"
    };
}

After that, we create an action method to return a view with the countries list:

public IActionResult SelectTagHelperWithListOfStrings()
{
    var model = new SelectViewModel
    {
        Countries = new SelectList(StaticRepository.GetCountries())
    };

    return View(model);

And render a countries dropdown with the help of a select tag helper:

@model SelectViewModel
@{
    ViewData["Title"] = "Countries dropdown";
}

<h3 class="mt-2">Countries Dropdown - Using a List of static strings</h3>

<select class="form-select-sm" asp-for="SelectedCountry" asp-items="@Model.Countries">
    <option>Please Select</option>
</select>

We are able to equate the asp-items directly to @Model.Countries because the Countries property is a SelectList.

Use an Enum to Render a Select Element

Let’s create a Department enum:

public enum Department
{
    IT,
    HR,
    Finance,
    Admin
}

Now, we can create an enum type property in a view model:

public class SampleViewModel
{
    public Department Department { get; set; }
}

After that, we can create an action method to return a view with the SampleViewModel:

public IActionResult SelectTagHelperWithEnum()
{
    var model = new SampleViewModel();
    return View(model);
}

Finally, we create the view and render the select element using the enum:

@model SampleViewModel
@{
    ViewData["Title"] = "Department dropdown";
}

<h3 class="mt-2">Department Dropdown - Using an enum</h3>

<select class="form-select-sm" asp-for="Department" asp-items="@Html.GetEnumSelectList<Department>()">
    <option>Please Select</option>
</select>

We are using @Html.GetEnumSelectList<T>() method to tie the asp-items when using enums.

Get the Selected Value of the Select Element in the Post Action Method

The model property tied to the asp-for attribute is responsible for getting the selected value of the select element:

public IActionResult Details()
{
    var model = new SelectViewModel
    {
        Genders = StaticRepository.GetGenders(),
        Employees = StaticRepository.GetEmployees(),
        Countries = new SelectList(StaticRepository.GetCountries())
    };
    return View(model);
}

[HttpPost]
public IActionResult Details(SelectViewModel model)
{
    var selectedGender = model.SelectedGender;
    var selectedEmployee = model.SelectedEmployeeId;
    var selectedCountry = model.SelectedCountry;
    var selectedDepartment = model.SelectedDepartment;

    return RedirectToAction("Details");
}

Let’s debug the application and submit the Details form:

post action method

All the selected properties get populated correctly.

How to Set a Default Value in the Select Element

In the GET action method, we need to set the properties that will be tied with the asp-for attribute.

We can tweak the GET action and explicitly set the individual properties:

public IActionResult Details()
{
    var model = new SelectViewModel
    {
        Genders = StaticRepository.GetGenders(),
        Employees = StaticRepository.GetEmployees(),
        Countries = new SelectList(StaticRepository.GetCountries()),
        SelectedGender = "Female",
        SelectedEmployeeId = 102,
        SelectedCountry = "USA",
        SelectedDepartment = 2
    };
    return View(model);
}

Now, we can run the project and browse the view:

multiple dropdowns

We see that all 4 dropdowns have a default option selected.

Render a Multi-Select Dropdown

We will be using the multiple attribute of the select tag helper to achieve this functionality.

Let’s create a separate view model and house the required properties:

public class MultiSelectViewModel
{
    public List<EmployeeViewModel> Employees { get; set; }
    public int[] SelectedEmployeeIds { get; set; }
}

The Employees property populates the option elements, while the SelectedEmployeeIds property that is an integer array will help to send multiple selected values to the post-action method when we submit the form.

Now, we can create the view:

@model MultiSelectViewModel
@{
    ViewData["Title"] = "Multi Select Dropdown";
}

<h3>Multi Select Dropdown</h3>
<form method="post">
    <div>
        <select class="form-select multi-select-dropdown" asp-for="SelectedEmployeeIds" multiple
                asp-items="new SelectList(@Model.Employees,
                                  nameof(EmployeeViewModel.Id),
                                  nameof(EmployeeViewModel.EmployeeName))">
        </select>
    </div>
    <div class="mt-4">
        <input type="submit" value="Submit" class="btn btn-primary" />
    </div>
</form>

After that, we run the application and browse the view:

multi select dropdown

Finally, we can create a POST action method and submit the form to get multiple selected values from the dropdown:

To view this content, you must be a member of Code's Patreon at $1 or more

multi select dropdown post

We get Mark’s and Dave’s employee ids in the SelectedEmployeeIds array when we submit the form.

Grouping Items in a Select Element

At times, we get the requirement to group option elements under some common classification in a dropdown.

SelectListItem class has a Group property that helps to group multiple options with the same group names under one classification.

We can create a method that will use the Group property and return a list of SelectListItem:

public static List<SelectListItem> GetCourses(SelectListGroup science, SelectListGroup humanities)
{
    return new List<SelectListItem>
    {
        new SelectListItem
        {
            Text  = "Physics",
            Value = "PH101",
            Group = science
        },
        new SelectListItem
        {
            Text = "Chemistry",
            Value = "CH101",
            Group = science
        },
        new SelectListItem
        {
            Text = "Mathematics",
            Value = "MT101",
            Group = science
        },
        new SelectListItem
        {
            Text = "English",
            Value = "EN101",
            Group = humanities
        },
        new SelectListItem
        {
            Text = "Environmental Studies",
            Value = "EN101",
            Group = humanities
        },
        new SelectListItem
        {
            Text = "Economics",
            Value = "EC101",
            Group = humanities
        }
    };
}

We have two groups – science and humanities. These groups have been assigned to the separate SelectListItem instances.

Now, we can create the action method:

public IActionResult Grouped()
{
    var sciences = new SelectListGroup { Name = "Science" };
    var humanities = new SelectListGroup { Name = "Humanities" };
    var model = new GroupViewModel
    {
        Courses = StaticRepository.GetCourses(sciences, humanities)
    };
    return View(model);
}

We create two SelectListGroup, assign the names “Science” and “Humanities” and call the StaticRepository.GetCourses() method.

Let’s create the select tag helper that demonstrates the grouped functionality:

@model GroupViewModel
@{
    ViewData["Title"] = "Grouped Dropdown";
}

<h3>Grouped drodown list</h3>
<select class="form-select-sm" asp-items="@Model.Courses">
    <option>Please Select</option>
</select>

Finally, we run the application and browse the view:

grouped select dropdown

The option elements are divided into Science and Humanities groups respectively.

Conclusion

In this article, we have learned about tag helpers, and how are they different from HTML helpers. We have learned in detail about the select tag helper, and the various ways we can render the select element.

This content is available exclusively to members of Code's Patreon at $0 or more.