Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DropDownList items null when posting to edit form

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?

like image 830
Steven Avatar asked Mar 05 '11 22:03

Steven


1 Answers

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);
}
like image 101
Darin Dimitrov Avatar answered Oct 22 '22 08:10

Darin Dimitrov