Model validation is checking required fields in a referenced model object, when the key is only required one

StackOverflow https://stackoverflow.com/questions/21967484

Question

I'm creating an edit form for a Student model:

public class Student
{
    [Key]
    public virtual int ID { get; set; }

    [Required]
    public virtual StudentGuardian Guardian { get; set; }
}

This Student has a StudentGuardian instance inside, the StudentGuardian has validation attributes on Name, Sex ... etc

public class StudentGuardian
{
    [Key]
    public virtual int ID { get; set; }

    [Required]
    public virtual string Name { get; set; }

    [Required]
    public virtual string MobilePhone { get; set; }

    [Required]
    public virtual Sex Sex { get; set; }
}

But at Student edit form I'm only interested in GuardianId. The point is when creating an edit form and make something like that in the form:

@Html.DropDownListFor(x => x.Student.Guardian.ID, <GUARDIANS_LIST>)

and since the Guardian object is required at Student model, so the MVC validation is asking me to enter Guardian.Name and Guardian.MobilePhone and etc,

How can I just enforce the validation to be Guardian.Id only not the entire object?

Was it helpful?

Solution

The sole idea of keeping StudentGuardianin Student is to create a 1-to-1 relationship between Student and StudentGuardian classes and not for rendering data to the view. By your approach you will be getting errors not only while editing the student entity but also while creating it. Trying using a view model as others have recommended. The following is just an attempt to help you understand better.

public class StudentViewModel
{
        public int StudentId { get; set; }

        public string Name { get; set; }

        //..other member variables..

        [Display(Name="Guardian"]
        public int GuardianId { get; set; }
        public virtual IEnumerable<StudentGuardian> Guardians { get; set; }

}

And then in your Edit Action of your Controller

    [HttpGet]
    public ActionResult Edit(int id = 0)
    {
        Student student = db.Students.Find(id);
        var model = new StudentViewModel();
        model.Name = student.Name;
        model.Guardians = db.Guardians.ToList();

        //or if using repository then call the method that fetches
        //.. you the list of objects 
        //..and bind it to the StudentViewModel instance created.

        //Other Properties you need..fetch and assign them here..
        //model.StudentId= student.Id; ... etc


        if (student == null)
        {
            return HttpNotFound();
        }
        return View(model); // return the viewModel instance.
    }

Bind your Edit View with the StudentViewModel as well.

@model MvcApplication.Models.ViewModels.StudentViewModel
@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Student</legend>

        @Html.HiddenFor(model => model.StudentId)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.GuardianId)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.GuardianId)
            @Html.DropDownListFor(model => model.GuardianId, new SelectList(Model.Guardians, "GuardianId", "GuardianName"),"Select")
        </div>


        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Receive the data back on a reference of StudentViewModel class

   [HttpPost]
   public ActionResult Edit(StudentViewModel model)
    {
          //..do whatever..Save to Database or something else..
    }

Try googling for ViewModels, you will get numerous resources.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top