ASP.NET Core MVC Employee Management – Index View with Modal Form and AJAX Create

 

✅ 1) Why did asp-for show an error like:

“IEnumerable<Employee> does not contain a definition for 'Name'…”

Explanation:

  • At the top of your Razor view you have:


    @model IEnumerable<DemoEmsCoreMVCMarch2025.Models.Employee>

    which means:

    “This view expects a model that is a collection (list) of Employee objects.”

  • But later in your modal form you wrote:


    <input asp-for="Name" ... />
  • The asp-for tag helper looks for a property named Name on the model.

  • But your model is IEnumerable<Employee> (i.e., a collection of employees).

  • A collection doesn’t have properties like NameGender etc. Those belong to a single Employee.

That’s why you get:

“IEnumerable<Employee> does not contain a definition for 'Name'…”

Why is dummy used?

In the table header, we often use:


@Html.DisplayNameFor(m => dummy.Name)

Why?

  • DisplayNameFor needs to know which property it is working on, so it can find:

    • Display name from [Display(Name="...")] attributes in your model,

    • or use the property name itself.

  • DisplayNameFor doesn’t actually render data; it just looks at the property metadata.

Since our model is IEnumerable<Employee>, we can’t say:


@Html.DisplayNameFor(m => m.Name) // invalid, because 'm' is IEnumerable

So we create:

var dummy = new DemoEmsCoreMVCMarch2025.Models.Employee();

and then write:

@Html.DisplayNameFor(m => dummy.Name)

This way, DisplayNameFor can still get the metadata of the Name property from an Employee object.


✅ 3) Why not use asp-for inside the modal?

Inside the modal form, if you wrote:

<input asp-for="Name" ... />

It would try to bind to the model: IEnumerable<Employee> — which is wrong.

Correct approach:

Since your modal is for creating one new employee, you should ideally:

  • Use a partial view whose @model is a single Employee
    or

  • Manually write <input> elements without asp-for.

For quick projects:
We often manually write:

<input class="form-control" id="name" />

and handle validation & posting with JavaScript (as shown).


✔ ASP.NET Core MVC view (index.cshtml partial with modal),

✔ CSS,
✔ full jQuery validation (red border + inline error),
all together, so you can copy-paste.


✅ Full updated index.cshtml (view)

@model IEnumerable<DemoEmsCoreMVCMarch2025.Models.Employee>


@{

    ViewData["Title"] = "Index";

    var dummy = new DemoEmsCoreMVCMarch2025.Models.Employee();

}


<h1>Index</h1>


<style>

    .input-error {

        border-color: red !important;

    }

</style>



<div class="container mt-3">

    <div class="d-flex align-items-center">

        <!--Add Employee-->

        <button type="button" class="btn btn-secondary me-2"

                data-bs-toggle="modal"

                data-bs-target="#createEmployeeModal">

            Create New

        </button>


        <!--Search Employee-->

        <input type="text" id="searchInput" class="form-control me-2"

               placeholder="Enter contact number"

               style="width: auto; flex-grow: 1;">

        <button id="searchButton" class="btn btn-primary">Search</button>

    </div>

</div>


<table class="table">

    <thead>

        <tr>

            <th>@Html.DisplayNameFor(m => dummy.Id)</th>

            <th>@Html.DisplayNameFor(m => dummy.Name)</th>

            <th>@Html.DisplayNameFor(m => dummy.Gender)</th>

            <th>@Html.DisplayNameFor(m => dummy.Designation)</th>

            <th>@Html.DisplayNameFor(m => dummy.Salary)</th>

            <th>@Html.DisplayNameFor(m => dummy.DOB)</th>

            <th>@Html.DisplayNameFor(m => dummy.Department.DepartmentName)</th>

            <th>@Html.DisplayNameFor(m => dummy.IsActive)</th>

            <th>@Html.DisplayNameFor(m => dummy.Contact)</th>

            <th></th>

        </tr>

    </thead>

    <tbody>

        @foreach (var item in Model)

        {

            <tr>

                <td>@Html.DisplayFor(m => item.Id)</td>

                <td>@Html.DisplayFor(m => item.Name)</td>

                <td>@Html.DisplayFor(m => item.Gender)</td>

                <td>@Html.DisplayFor(m => item.Designation)</td>

                <td>@Html.DisplayFor(m => item.Salary)</td>

                <td>@Html.DisplayFor(m => item.DOB)</td>

                <td>@Html.DisplayFor(m => item.Department.DepartmentName)</td>

                <td>@Html.DisplayFor(m => item.IsActive)</td>

                <td>@Html.DisplayFor(m => item.Contact)</td>

                <td>

                    @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |

                    @Html.ActionLink("Details", "Details", new { id = item.Id }) |

                    @Html.ActionLink("Delete", "Delete", new { id = item.Id })

                </td>

            </tr>

        }

    </tbody>

</table>


<!-- Modal -->

<div class="modal fade" id="createEmployeeModal" tabindex="-1"

     aria-labelledby="exampleModalLabel" aria-hidden="true">


    <div class="modal-dialog">

        <div class="modal-content">

            <div class="modal-header">

                <h5 class="modal-title">Create Employee</h5>

                <button type="button" class="btn-close" data-bs-dismiss="modal"

                        aria-label="Close"></button>

            </div>

            <div class="modal-body">

                <form id="createEmployeeForm">

                    <!-- Name -->

                    <div class="form-group">

                        <label>Name <span class="text-danger">*</span></label>

                        <input class="form-control" id="name" autocomplete="off" />

                        <span id="nameError" class="text-danger"></span>

                    </div>


                    <!-- Gender -->

                    <div class="form-group">

                        <label>Gender <span class="text-danger">*</span></label>

                        <div>

                            <input type="radio" name="Gender" value="Male" id="genderMale" /> <label for="genderMale">Male</label>

                        </div>

                        <div>

                            <input type="radio" name="Gender" value="Female" id="genderFemale" /> <label for="genderFemale">Female</label>

                        </div>

                        <div>

                            <input type="radio" name="Gender" value="Other" id="genderOther" /> <label for="genderOther">Other</label>

                        </div>

                        <span id="genderError" class="text-danger"></span>

                    </div>


                    <!-- Designation -->

                    <div class="form-group">

                        <label>Designation <span class="text-danger">*</span></label>

                        <input class="form-control" id="designation" autocomplete="off" />

                        <span id="designationError" class="text-danger"></span>

                    </div>


                    <!-- Contact -->

                    <div class="form-group">

                        <label>Contact <span class="text-danger">*</span></label>

                        <input class="form-control" id="contact" autocomplete="off" />

                        <span id="contactError" class="text-danger"></span>

                    </div>


                    <!-- Salary -->

                    <div class="form-group">

                        <label>Salary <span class="text-danger">*</span></label>

                        <input class="form-control" id="salary" type="number" autocomplete="off" />

                        <span id="salaryError" class="text-danger"></span>

                    </div>


                    <!-- DOB -->

                    <div class="form-group">

                        <label>Date of Birth <span class="text-danger">*</span></label>

                        <input class="form-control" id="dob" type="date" />

                        <span id="dobError" class="text-danger"></span>

                    </div>


                    <!-- Department -->

                    <div class="form-group">

                        <label>Department <span class="text-danger">*</span></label>

                        <select id="departmentList" class="form-control">

                            <option value="">---Select Department---</option>

                            @foreach (var department in ViewBag.Departments)

                            {

                                <option value="@department.DepartmentId">@department.DepartmentName</option>

                            }

                        </select>

                        <span id="departmentError" class="text-danger"></span>

                    </div>


                    <!-- IsActive -->

                    <div class="form-group form-check">

                        <input type="checkbox" id="IsActive" class="form-check-input" checked />

                        <label class="form-check-label">Is Active</label>

                    </div>

                </form>

            </div>

            <div class="modal-footer">

                <button type="button" class="btn btn-secondary"

                        data-bs-dismiss="modal">

                    Close

                </button>

                <button type="button" id="btnSave" class="btn btn-primary">Save</button>

            </div>

        </div>

    </div>

</div>

@section Scripts {

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <script>

        $(document).ready(function () {

            $("#btnSave").click(function (e) {

                e.preventDefault();


                // Clear previous errors

                $(".form-control").removeClass("input-error");

                $(".text-danger").text("");


                var hasError = false;


                var name = $("#name").val().trim();

                var gender = $("input[name='Gender']:checked").val();

                var designation = $("#designation").val().trim();

                var contact = $("#contact").val().trim();

                var salary = $("#salary").val().trim();

                var dob = $("#dob").val().trim();

                var departmentId = $("#departmentList").val();


                if (!name) {

                    $("#name").addClass("input-error");

                    $("#nameError").text("Name is required.");

                    hasError = true;

                }

                if (!gender) {

                    $("#genderError").text("Gender is required.");

                    hasError = true;

                }

                if (!designation) {

                    $("#designation").addClass("input-error");

                    $("#designationError").text("Designation is required.");

                    hasError = true;

                }

                if (!contact) {

                    $("#contact").addClass("input-error");

                    $("#contactError").text("Contact is required.");

                    hasError = true;

                }

                if (!salary || parseFloat(salary) <= 0) {

                    $("#salary").addClass("input-error");

                    $("#salaryError").text("Enter valid salary.");

                    hasError = true;

                }

                if (!dob) {

                    $("#dob").addClass("input-error");

                    $("#dobError").text("DOB is required.");

                    hasError = true;

                }

                if (!departmentId) {

                    $("#departmentList").addClass("input-error");

                    $("#departmentError").text("Select department.");

                    hasError = true;

                }


                if (hasError) return;


                var formData = {

                    Name: name,

                    Gender: gender,

                    Designation: designation,

                    Contact: contact,

                    Salary: salary,

                    DOB: dob,

                    DepartmentId: departmentId,

                    IsActive: $("#IsActive").is(":checked")

                };


                $.ajax({

                    type: "POST",

                    url: "@Url.Action("Create", "Employees")",

                    data: formData,

                    success: function () {

                        $('#createEmployeeModal').modal('hide');

                        location.reload();

                    },

                    error: function () {

                        alert("Error adding employee.");

                    }

                });

            });

        });

    </script>

}


Comments

Popular posts from this blog

Interview Tips: Dot NET Framework vs Net CORE

FREE Webinar: Run Your Own Independent DeepSeek LLM

Delegates and Events