Select Tag Helper in ASP.NET Core MVC
Using the Select Tag helpers to render a SELECT element
In your GET action, create an object of your view model, load the EmployeeList
collection property and send that to the view.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.EmployeesList = new List<Employee>
{
new Employee { Id = 1, FullName = "Shyju" },
new Employee { Id = 2, FullName = "Bryan" }
};
return View(vm);
}
And in your create view, create a new SelectList
object from the EmployeeList
property and pass that as value for the asp-items
property.
@model MyViewModel
<form asp-controller="Home" asp-action="Create">
<select asp-for="EmployeeId"
asp-items="@(new SelectList(Model.EmployeesList, nameof(Employee.Id), nameof(Employee.FullName)))">
<option>Please select one</option>
</select>
<input type="submit"/>
</form>
And your HttpPost action method to accept the submitted form data.
[HttpPost]
public IActionResult Create(MyViewModel model)
{
// check model.EmployeeId
// to do : Save and redirect
}
Or
If your view model has a List<SelectListItem>
as the property for your dropdown items.
public class MyViewModel
{
public int EmployeeId { get; set; }
public string Comments { get; set; }
public List<SelectListItem> Employees { set; get; }
}
And in your get action,
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "1"},
new SelectListItem {Text = "Sean", Value = "2"}
};
return View(vm);
}
And in the view, you can directly use the Employees
property for the asp-items
.
@model MyViewModel
<form asp-controller="Home" asp-action="Create">
<label>Comments</label>
<input type="text" asp-for="Comments"/>
<label>Lucky Employee</label>
<select asp-for="EmployeeId" asp-items="@Model.Employees" >
<option>Please select one</option>
</select>
<input type="submit"/>
</form>
The class SelectListItem
belongs to Microsoft.AspNet.Mvc.Rendering
namespace.
Make sure you are using an explicit closing tag for the select element. If you use the self closing tag approach, the tag helper will render an empty SELECT element!
The below approach will not work
<select asp-for="EmployeeId" asp-items="@Model.Employees" />
But this will work.
<select asp-for="EmployeeId" asp-items="@Model.Employees"></select>
Getting data from your database table using entity framework
The above examples are using hard coded items for the options. So i thought i will add some sample code to get data using Entity framework as a lot of people use that.
Let's assume your DbContext object has a property called Employees
, which is of type DbSet<Employee>
where the Employee
entity class has an Id
and Name
property like this
public class Employee
{
public int Id { set; get; }
public string Name { set; get; }
}
You can use a LINQ query to get the employees and use the Select method in your LINQ expression to create a list of SelectListItem
objects for each employee.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = context.Employees
.Select(a => new SelectListItem() {
Value = a.Id.ToString(),
Text = a.Name
})
.ToList();
return View(vm);
}
Assuming context
is your db context object. The view code is same as above.
Using SelectList
Some people prefer to use SelectList
class to hold the items needed to render the options.
public class MyViewModel
{
public int EmployeeId { get; set; }
public SelectList Employees { set; get; }
}
Now in your GET action, you can use the SelectList
constructor to populate the Employees
property of the view model. Make sure you are specifying the dataValueField
and dataTextField
parameters. You can use a nameof expression to link the field names statically.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new SelectList(GetEmployees(), nameof(Employee.Id), nameof(Employee.FirstName));
return View(vm);
}
public IEnumerable<Employee> GetEmployees()
{
// hard coded list for demo.
// You may replace with real data from database to create Employee objects
return new List<Employee>
{
new Employee { Id = 1, FirstName = "Shyju" },
new Employee { Id = 2, FirstName = "Bryan" }
};
}
Here I am calling the GetEmployees
method to get a list of Employee objects, each with an Id
and FirstName
property and I use those properties as DataValueField
and DataTextField
of the SelectList
object we created. You can change the hardcoded list to a code which reads data from a database table.
The view code will be same.
<select asp-for="EmployeeId" asp-items="@Model.Employees" >
<option>Please select one</option>
</select>
Render a SELECT element from a list of strings.
Sometimes you might want to render a select element from a list of strings. In that case, you can use the SelectList
constructor which only takes IEnumerable<T>
var vm = new MyViewModel();
var items = new List<string> {"Monday", "Tuesday", "Wednesday"};
vm.Employees = new SelectList(items);
return View(vm);
The view code will be same.
Setting selected options
Some times,you might want to set one option as the default option in the SELECT element (For example, in an edit screen, you want to load the previously saved option value). To do that, you may simply set the EmployeeId
property value to the value of the option you want to be selected.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "11"},
new SelectListItem {Text = "Tom", Value = "12"},
new SelectListItem {Text = "Jerry", Value = "13"}
};
vm.EmployeeId = 12; // Here you set the value
return View(vm);
}
This will select the option Tom in the select element when the page is rendered.
Multi select dropdown
If you want to render a multi select dropdown, you can simply change your view model property which you use for asp-for
attribute in your view to an array type.
public class MyViewModel
{
public int[] EmployeeIds { get; set; }
public List<SelectListItem> Employees { set; get; }
}
This will render the HTML markup for the select element with the multiple
attribute which will allow the user to select multiple options.
@model MyViewModel
<select id="EmployeeIds" multiple="multiple" name="EmployeeIds">
<option>Please select one</option>
<option value="1">Shyju</option>
<option value="2">Sean</option>
</select>
Setting selected options in multi select
Similar to single select, set the EmployeeIds
property value to the an array of values you want.
public IActionResult Create()
{
var vm = new MyViewModel();
vm.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "11"},
new SelectListItem {Text = "Tom", Value = "12"},
new SelectListItem {Text = "Jerry", Value = "13"}
};
vm.EmployeeIds= new int[] { 12,13} ;
return View(vm);
}
This will select the option Tom and Jerry in the multi select element when the page is rendered.
Using ViewBag to transfer the list of items
If you do not prefer to keep a collection type property to pass the list of options to the view, you can use the dynamic ViewBag to do so.(This is not my personally recommended approach as viewbag is dynamic and your code is prone to uncaught typo errors)
public IActionResult Create()
{
ViewBag.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "1"},
new SelectListItem {Text = "Sean", Value = "2"}
};
return View(new MyViewModel());
}
and in the view
<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
<option>Please select one</option>
</select>
Using ViewBag to transfer the list of items and setting selected option
It is same as above. All you have to do is, set the property (for which you are binding the dropdown for) value to the value of the option you want to be selected.
public IActionResult Create()
{
ViewBag.Employees = new List<SelectListItem>
{
new SelectListItem {Text = "Shyju", Value = "1"},
new SelectListItem {Text = "Bryan", Value = "2"},
new SelectListItem {Text = "Sean", Value = "3"}
};
vm.EmployeeId = 2; // This will set Bryan as selected
return View(new MyViewModel());
}
and in the view
<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
<option>Please select one</option>
</select>
Grouping items
The select tag helper method supports grouping options in a dropdown. All you have to do is, specify the Group
property value of each SelectListItem
in your action method.
public IActionResult Create()
{
var vm = new MyViewModel();
var group1 = new SelectListGroup { Name = "Dev Team" };
var group2 = new SelectListGroup { Name = "QA Team" };
var employeeList = new List<SelectListItem>()
{
new SelectListItem() { Value = "1", Text = "Shyju", Group = group1 },
new SelectListItem() { Value = "2", Text = "Bryan", Group = group1 },
new SelectListItem() { Value = "3", Text = "Kevin", Group = group2 },
new SelectListItem() { Value = "4", Text = "Alex", Group = group2 }
};
vm.Employees = employeeList;
return View(vm);
}
There is no change in the view code. the select tag helper will now render the options inside 2 optgroup items.
Select tag helper from database ASP.NET Core 3.1
If you'd like to retrieve data from db and populate a dropdown with retrieved data through a view model (or ViewBag), you can refer to following code snippet.
In AdminUser
view model class, include these properties
public string Selected_Glossary { get; set; }
public List<SelectListItem> Glossary_List { get; set; }
In controller
public IActionResult Create(AdminUser model)
{
var adminuser_model = new AdminUser
{
UserName="test"
//for other properties
};
//retrieve data from Glossary table
var items = _context.Glossary.Where(x => x.Category == 1).Select(x => new SelectListItem
{
Value = x.UniqueId.ToString(),
Text = x.DisplayText
}).ToList();
//pass dropdown items through a view model
adminuser_model.Glossary_List = items;
////pass dropdown items through ViewBag
//ViewBag.Glossary_List = items;
return View(adminuser_model);
}
In view page
@model AdminUser
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<form asp-controller="Home" asp-action="Create" method="post">
<select asp-for="Selected_Glossary" asp-items="Model.Glossary_List"></select>
@*populate it through ViewBag*@
@*<select asp-for="Selected_Glossary" asp-items="ViewBag.Glossary_List"></select>*@
<input type="submit" value="Submit" />
</form>
Test Result
asp.net core select with tag-helpers, make a specif option tag be selected
According to the code you shared, try the following...
<select asp-for="ProjectId" asp-items="@(new SelectList(projects, nameof(Project.ProjectId), nameof(Project.Name), SomeModel.SelectedProjectId))"></select>
You add a third parameter to SelectList with the selected value.
Here is the reference of SelectList constructors:
https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.selectlist.-ctor?view=aspnet-mvc-5.2#system-web-mvc-selectlist-ctor(system-collections-ienumerable-system-string-system-string-system-object)
Create dropdownlist using select tag helper of a view model in .NET Core Razor Pages (Not MVC)
Found the solution with this syntax
<select asp-for="MovieId" asp-items="ViewBag.MovieId">
<option value="">Pick one</option>
</select>
Select an option in a select element with tag helpers
You're not doing anything with the asp-for
. It's not magic. If you look at the code for one of the built-in tag helpers, you'll see they have property for capturing this, along the lines of:
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; }
Then, you must use this property to actually set the selected option by reading the value. That said, though, you'd probably be better served by simply inheriting your tag helper from SelectTagHelper
, and just overriding Process
to do your own logic. Remember to call base.Process
as well, though.
Asp.net core How to bind data and get value of select TagHelper?
change asp-for="systemName" to asp-for="SystemLevel"!
<div class="form-group">
<select asp-for="SystemLevel" asp-items="@(new SelectList(ViewBag.SysList,"id","systemName"))" class="form-control"></select>
</div>
How to pass multiple select data with TagHelpers in ASP.NET Core MVC
In your select, the option field value is id
, hence you should expect a list of Product.id
.
Follow the steps below;
- Make a view model where we will bind the Name and Id list.
public class ProductCategoryCreateViewModel {
public string Name {get;set;}
public List<int> ProductIds {get;set;}
}
- Use the code below for controller, see comments.
[HttpPost]
[ValidateAntiForgeryToken]
// bind the form data to the view model
public IActionResult Create(ProductCategoryCreateViewModel viewModel)
{
if (!ModelState.IsValid)
return RedirectToAction("Create");
Context c = new Context();
// make a new ProductCategory using the ViewModel
ProductCategory newCategory = new ProductCategory();
// assign name to new category
newCategory.Name = viewModel.Name;
// save the category first so it will generate a new category id
c.ProductCategories.Add(newCategory);
c.SaveChanges();
// loop through all product ids selected, and update them with the newcategoryid
foreach(var id in viewModel.ProductIds){
// load the product
var updateProduct = c.Products.FirstOrDefault(p=>p.id == id);
if(updateProduct != null){
// if product is found, update the category id
updateProduct.Categoryid = newCategory.id;
c.SaveChanges();
}
}
return RedirectToAction("Index");
}
- Add
name="ProductIds"
to select tag. Removefor
attribute.
<select name="ProductIds" id="Products" class="form-control" multiple>
...
</select>
ASP.NET Core : Tag helper select is empty
I have tested your code on my side. Problem is in your select
tag. You are using self closing select tag. This will not work. Write your select tag as follows:
<select asp-for="Status" class="form-control" asp-items="Model.Statuses">
<option value="">Select Status</option>
</select>
You have also problem in your SelectList
initialization. The way you have initialized SelectList
would not work. Initialize your SelectList
as follows:
public EditTicketVM()
{
Statuses = new SelectList(new List<SelectListItem> {
new SelectListItem(){Text = "Open", Value = "open"},
new SelectListItem(){Text = "Pending", Value = "pending"},
new SelectListItem(){Text = "Hold", Value = "hold"},
new SelectListItem(){Text = "Solved", Value = "solved"},
new SelectListItem(){Text = "Closed", Value = "closed"},
},"Value","Text");
}
Force single select with Razor Select Tag Helper
Based on the comment from Mike Brind, I was able to solve my problem by simply deactivating the tag helpers for my two select
-Tags like so:
<!select name="TätigkeitIds" required onchange="this.form.submit()" @(Model.Erfassung.TätigkeitNavigation != null && Boolean.Equals(Model.Erfassung.TätigkeitNavigation.Abzurechnen, false) ? "disabled" : "")>
@{
<option selected=@(Model.Erfassung.TätigkeitNavigation == null || Boolean.Equals(Model.Erfassung.TätigkeitNavigation.Abzurechnen, false)) value="">nicht abrech. Std.</option>
foreach(StammdatenTätigkeit Tätigkeit in await Model.GetTätigkeitenAsync(true))
{
<option selected="@(Model.Erfassung.TätigkeitNavigation != null && String.Equals(Tätigkeit.Id, Model.Erfassung.TätigkeitNavigation.Id))" value=@Tätigkeit.Id>@Tätigkeit.Name</option>
}
}
</!select>
Related Topics
Automating the Invokerequired Code Pattern
Validation Failed For One or More Entities. See 'Entityvalidationerrors' Property For More Details
Entity Framework Code First - Two Foreign Keys from Same Table
Download Excel File Via Ajax MVC
Public Fields Versus Automatic Properties
Evaluating String "3*(4+2)" Yield Int 18
What Is the Best Workaround For the Wcf Client 'Using' Block Issue
How to Provide User Name and Password When Connecting to a Network Share
Does Json.Net Cache Types' Serialization Information
Difference Between Property and Field in C# 3.0+
What Are the Correct Version Numbers For C#
How to Convert Utf-8 Byte[] to String
What's the Fastest Way to Read a Text File Line-By-Line
Send Http Post Request in .Net
Ienumerable VS List - What to Use - How Do They Work