So I have a page to edit employees.
Here is my view model:
public class EmployeesViewModel
{
[HiddenInput(DisplayValue = false)]
public int EmployeeId { get; set; }
[Required(ErrorMessage = "Position is required")]
[DisplayName("Position")]
public int EmployeeTypeId { get; set; }
[Required(ErrorMessage = "Name is required")]
[DisplayName("Name")]
public string Name { get; set; }
public IEnumerable<EmployeeType> EmployeeTypes { get; set; }
}
Here is my controller:
public class EmployeesController : Controller
{
public ActionResult Edit(int id)
{
//get employee from id
var employee = GetEmployee(id);
if (employee != null)
{
var viewModel = new EmployeesViewModel
{
EmployeeId = employee.EmployeeID,
EmployeeTypeId = employee.EmployeeTypeID,
Name = employee.Name,
EmployeeTypes = _adminRepository.GetAllEmployeeTypes(),
};
return View(viewModel);
}
//if no employee exists for this id, redirect to the Create page and display a friendly message
TempData["message"] = "No employee exists with an ID of " + id + ", you can create a new employee here.";
return RedirectToAction("Create");
}
[HttpPost]
public ActionResult Edit(EmployeesViewModel viewModel)
{
//if editing an employee, fetch it; otherwise, create a new one
Employee employee = GetEmployee(viewModel.EmployeeId);
TryUpdateModel(employee);
if (ModelState.IsValid)
{
SaveEmployee(employee);
TempData["message"] = "Employee has been saved.";
return RedirectToAction("Details", new { id = employee.EmployeeID });
}
return View(viewModel); // validation error, so redisplay same view
}
}
And my Edit view page:
<%@ Page Title="" Language="C#" MasterPageFile="/Admin.Master" Inherits="System.Web.Mvc.ViewPage<EmployeesViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Edit Employee</h1>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("Edit", "Employees", FormMethod.Post)) { %>
<%: Html.HiddenFor(m => m.EmployeeId)%>
<div class="editor-label"><%: Html.LabelFor(m => m.EmployeeTypeId) %></div>
<div class="editor-field">
<%= Html.DropDownListFor(m => m.EmployeeTypeId, new SelectList(Model.EmployeeTypes, "EmployeeTypeID", "Position", Model.EmployeeTypeId), "- Select an Employee Type -")%>
<%: Html.ValidationMessageFor(m => m.EmployeeTypeId)%>
</div>
<div class="editor-label"><%: Html.LabelFor(m => m.Name) %></div>
<div class="editor-field">
<%: Html.TextBoxFor(m => m.Name)%>
<%: Html.ValidationMessageFor(m => m.Name)%>
</div>
<p>
<input type="submit" value="Save" />
<%: Html.ActionLink("Cancel", "Index") %>
</p>
<% } %>
</asp:Content>
After submitting my form, it fails at if (ModelState.IsValid)
. It tries to redisplay the view when return View(viewModel);
is called, and I get this error message:
Value cannot be null.
Parameter name: items
<%= Html.DropDownListFor(m => m.EmployeeTypeId, new SelectList(Model.EmployeeTypes, "EmployeeTypeID", "Position", Model.EmployeeTypeId), "- Select an Employee Type -")%>
I'm not sure why this is happening. The dropdown is loaded correctly when I navigate to the page, but not when the view is redisplayed.
Does anyone know what's going on here?
You need to reload the EmployeeTypes
property on your view model from your repository before redisplaying the view in case of error. This property is never posted so it would be always be null inside your POST action and when the view is rendered the helper would throw an exception:
[HttpPost]
public ActionResult Edit(EmployeesViewModel viewModel)
{
//if editing an employee, fetch it; otherwise, create a new one
Employee employee = GetEmployee(viewModel.EmployeeId);
TryUpdateModel(employee);
if (ModelState.IsValid)
{
SaveEmployee(employee);
TempData["message"] = "Employee has been saved.";
return RedirectToAction("Details", new { id = employee.EmployeeID });
}
// Reload employee types from repository before redisplaying the view
viewModel.EmployeeTypes = _adminRepository.GetAllEmployeeTypes();
// validation error, so redisplay same view
return View(viewModel);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With