0

I'll only include the relevant properties of the model and the related lines for simplicity:

Model: Department.cs
Property: public virtual Staff HOD { get; set; }

ControllerMethod:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Add([Bind] Department newDepartment)
{
    await _departmentRepository.AddDepartmentAsync(newDepartment);
    await _departmentRepository.SaveTransactionAsync(true);
    return Redirect("Details" + "/" + newDepartment.Id);
}

View:

@model Department
@inject IStaffRepository staffRepository

@{
    // select list
    var listOfEmployees = new List<Staff>();
    foreach (var staff in await staffRepository.GetAllStaffAsync())
    {
        listOfEmployees.Add(staff);
    }
    var selectListHOD = new SelectList(listOfEmployees, "EmployeeId", "Name"); //populates the option element with the correct Employee Id
}

<form class="form-group" method="post">
    <div class="d-flex flex-column">
        <div class="input-group" style="margin-bottom: 1%">
            @Html.DropDownListFor(department => department.HOD, selectListHOD, htmlAttributes: new { @class="form-control" })
        </div>
        <div class="input-group">
            <input class="btn btn-primary" type="submit" value="Save" />
        </div>
    </div>
</form>

Result:
(I have not included the other properties seen here in the question, but trust me, the properties of the parameter to the controller get correctly populated with them, except for the HOD property) The Generated View


Source:

<form class="form-group" method="post">
    <div class="d-flex flex-column">
        <div class="input-group" style="margin-bottom: 1%">
            <input class="form-control" id="Id" name="Id" placeholder="Id" type="text" value="" /> </div>
        <div class="input-group" style="margin-bottom: 1%">
            <input class="form-control" id="Name" name="Name" placeholder="Department" type="text" value="" /> </div>
        <div class="input-group" style="margin-bottom: 1%">
            <input class="form-control" id="Description" name="Description" placeholder="Description" type="text" value="" /> </div>
        <div class="input-group" style="margin-bottom: 1%">
            <select class="form-control" id="HOD" name="HOD">
                <option value="EMP01">Employee 1</option>
                <option value="EMP02">Employee 2</option>
            </select>
        </div>
        <div class="input-group">
            <input class="btn btn-primary" type="submit" value="Save" /> </div>
    </div>
    <input name="__RequestVerificationToken" type="hidden" value="CfDJ8AIwSWkSO0hJqMxy-oQKoeG35LTDmI2N1XHDZL9qeaxRxc17TyZbT2z9Iq0GMPkRyE7HnaX1r4ZSIs0bQATYB7w_A_HZDBXGETMmpdSqlMXZCmf7cH9ECzrNGz0Wuu9zHkE50yI92vPY-GxNPG-pRhs" /> 
</form>

My guess is that the value being supplied to the controller seems to be wrong. How would I pass the actual object instead of the ID?
I tried using this instead of EmployeeId, but it throws Object Reference not found exception.

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39
  • Short answer; If you don't have a html input / select for each property, then no value will be bound. IMHO I prefer tag helpers with `asp-for` over `Html.DropDownListFor...` https://learn.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-6.0#the-input-tag-helper. – Jeremy Lakeman Nov 29 '21 at 02:46

1 Answers1

1

You cannot bind an object with <select></select>.You can try to bind Hod.EmployeeId with <select></select>.And add a hidden input to bind Hod.Name.When selected value changes,change the value of hidden input.Here is a demo:

<form class="form-group" method="post">
    <div class="d-flex flex-column">
        <div class="input-group" style="margin-bottom: 1%">
            @Html.DropDownListFor(department => department.HOD.EmployeeId, selectListHOD, htmlAttributes: new { @class = "form-control",@onChange= "AddName()" })
            <input hidden asp-for="HOD.Name" />
        </div>
        <div class="input-group">
            <input class="btn btn-primary" type="submit" value="Save" />
        </div>
    </div>
</form>
@section scripts
{
    <script>
        $(function () {
            AddName();
        })
        function AddName() {
            $("#HOD_Name").val($("#HOD_EmployeeId option:selected").text());
        }
    </script>
}

result: enter image description here

Yiyi You
  • 16,875
  • 1
  • 10
  • 22
  • Why did we have to use that `$` thingy? – kesarling He-Him Nov 29 '21 at 05:07
  • `$ is simply a valid JavaScript identifier.`.You can refer to the the [link](https://stackoverflow.com/questions/1150381/what-is-the-meaning-of-sign-in-javascript). – Yiyi You Nov 29 '21 at 05:45
  • Yes, but why did we have to write `$(function () { AddName(); })` in the first place? Couldn't we simply have written `` instead? – kesarling He-Him Nov 29 '21 at 06:58
  • `$(function () { AddName(); })` will help you set the value pf the hidden input when page load.So that if you don't change the default selected value of dropdown,the hidden input's value will be the name of the default selected option. – Yiyi You Nov 29 '21 at 07:01