I have a drop down list on my Razor page. I am binding the drop down list with a ViewData. below is the code for my controller where I am getting the data from the database:
public async Task<IActionResult> Index()
{
List<DocumentType> docTypes = new List<DocumentType>();
docTypes = await _documentTypeService.GetDocumentTypes(deptId);
ViewData["DocumentType"] = new SelectList(docTypes, "Id", "Description");
}
This is how I am displaying the drop down list and I am also selecting a value for the drop down based on certain condition.
This is the view markup:
<table class="table table-bordered">
<thead>
<tr>
<th>Type</th>
</thead>
<tbody>
@if (Model != null)
{
@foreach (var item in Model)
{
string selected = String.Empty;
@foreach (var code in (SelectList)ViewData["DocumentType"])
{
if (code.Text.Contains("This is the test for RCA-500"))
{
selected = code.Text;
break;
}
}
<tr>
<td>
<select class="form-control" style="min-width:150px" id="[email protected]" asp-items="@(new SelectList(ViewBag.DocumentType,selected))" asp-for="@item.DocumentType"></select>
</td>
</tr>
This drop down is displaying "Microsoft.AspNetCore.Mvc.Rendering.SelectlistItem" instead of the actual values. Not sure what am I doing wrong.
I tried removing the @
symbol from asp-items, but then I start getting a compiler error saying ";" is missing.
You have to provide the property name for the text displayed and its value as below.
<select class="form-control" style="min-width:150px" id="[email protected]"
asp-items="@(new SelectList(ViewBag.DocumentType, "Value", "Text", selected))"
asp-for="@item.DocumentType">
</select>
However, I believe the approach above will not programmatically select the correct option as it will bind the value based on DocumentType
's value.
You should set the desired selected option to DocumentType
instead of using the selected
variable.
@foreach (var code in (SelectList)ViewData["DocumentType"])
{
if (code.Text.Contains("This is the test for RCA-500"))
{
item.DocumentType = Convert.ToInt32(code.Value); // Convert the `Value` to the `DocumentType` type
break;
}
}
<tr>
<td>
<select class="form-control" style="min-width:150px" id="[email protected]"
asp-items="@(ViewBag.DocumentType as SelectList)"
asp-for="@item.DocumentType">
</select>
</td>
</tr>
Without the foreach
loop, you can achieve with First()
from the System.Linq.
@using System.Linq; // Place on the top of the page
@foreach (var item in Model)
{
item.DocumentType = Convert.ToInt32(((SelectList)ViewData["DocumentType"]).First(x => x.Text.Contains("This is the test for RCA-500")).Value);
<tr>
<td>
<select class="form-control" style="min-width:150px" id="[email protected]"
asp-items="@(ViewBag.DocumentType as SelectList)"
asp-for="@item.DocumentType">
</select>
</td>
</tr>
}
And the above logic can be done in the controller action.