Arjun Hariharan
Arjun Hariharan

Reputation: 330

ModelState.IsValid is false when binded to dropdownlist

Model:

faculty class

[Key]
[Required(ErrorMessage="*Enter Faculty id")]
[StringLength(5)]
public string Id { get; set; }

[Required(ErrorMessage="*Enter First Name")]
[MaxLength(30)]
public string F_Name { get; set; }

[Required(ErrorMessage="*Enter Last Name")]
[MaxLength(30)]
public string L_Name { get; set; }

[MaxLength(30)]
public string M_Name { get; set; }

[Required(ErrorMessage="*Enter Email id")]
[MaxLength(50)]
public string Email{ get; set; }

[Required(ErrorMessage="*Enter Department")]
public Int16 Dept_Id { get; set; }
[ForeignKey("Dept_Id")]
public virtual Department Dept { get; set; }

Department class:

public class Department  //static table
{
    [Key]
    public Int16 Id { get; set; }
    [Required]
    [MaxLength(20)]
    public string Dept_Name { get; set; }
}

View:

<div class="editor-label">
        Faculty Id
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Id, new { style = "width:200px;"})
        @Html.ValidationMessageFor(model => model.Id,null, new { style="color:Red"})
    </div>

     <div class="editor-label">
        First Name
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.F_Name,new { style = "width:200px;"})
        @Html.ValidationMessageFor(model => model.F_Name, null, new { style="color:red;"})
    </div>

    <div class="editor-label">
        Middle Name
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.M_Name,new { style = "width:200px;"})
        @Html.ValidationMessageFor(model => model.M_Name)
    </div>

    <div class="editor-label">
        Last Name
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.L_Name,new { style = "width:200px;"})
        @Html.ValidationMessageFor(model => model.L_Name, null, new { style="color:red;"})
    </div>

    <div class="editor-label">
        Department
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model =>model.Dept_Id ,ViewBag.Dept_Id as IEnumerable<SelectListItem>,
        string.Empty,new { style = "width:200px;text-align:center;"})
        @Html.ValidationMessageFor(model => model.Dept_Id, null, new { style="color:red;"})
    </div>


    <p>
        <input type="submit" value="Create" />
    </p>

Controller:

[HttpPost]
public ActionResult Create(Faculty faculty)
{
    faculty.Email = faculty.F_Name + "." + faculty.L_Name + "@mitcoe.edu.in";
    if (ModelState.IsValid)
    {
        db.Faculty.Add(faculty);
        db.SaveChanges();
        return RedirectToAction("Index");
    }


    ViewBag.Dept_Id = new SelectList(db.Department, "Id", "Dept_Name", faculty.Dept_Id);
    return View(faculty);
}

The drop down list works fine and the ID for all the fields is fetched properly from the view.
But in the post function the modelstate is invalid as the Dept_name is null.
ORM creates the tables with only Dept_Id as a foreign key.
Why is the controller expecting Dept_Name also? Is anything wrong with my models?

Upvotes: 0

Views: 1465

Answers (1)

ngm
ngm

Reputation: 7487

The controller is expecting Dept_Name because:

  • You are model binding to the Faculty class.
  • Department is a component of Faculty.
  • Dept_Name is a required field on Department.

Dept_Name is null when the model binding parses the form data, as you do not have it as an input anywhere in you view.

Two suggestions, either:

  • Have a separate FacultyInputModel class which is the parameter to the Create action method. FacultyInputModel includes only those properties which you expect to be returned from the form;
  • Or: Use HiddenFor with the Dept_Name property, so it is included in your form data posted from you view and the model state is valid.

I'd recommend the first personally. It can be useful sometimes to separate your view models, i.e. what data you are displaying, from your input models, i.e. what data you expect to be posted back. It does add more classes and complexity though, on the down side. See e.g. https://www.simple-talk.com/dotnet/asp.net/the-three-models-of-asp.net-mvc-apps/ for a bit about input models.

Upvotes: 1

Related Questions