skip to Main Content

I’m trying to build a form for information about upcoming exams. My plan is to make a dropdown list which shows a List of teachers to chose from and who will be responsible for the exam.

Here’s a simplified version of my Models:

public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string Surname { get; set; }
    }
public class Teacher
    {
        public int Id { get; set; }
        public int PersonId { get; set; }
        public Person Person { get; set; }
    }
public class Exam
    {
        public int Id { get; set; }
        public string Subject { get; set; }
        public DateTime ExamDate { get; set; }
        public int TeacherId { get; set; }
        public Teacher Teacher { get; set; }
    }

My ViewModel:

public class ExamViewModel
    {
        public Exam Exam { get; set; }
        public IEnumerable<Person> People { get; set; }
        public IEnumerable<Teacher> Teachers { get; set; }
    }

And my Create action from ExamController:

public ActionResult Create()
        {
            var people = _context.People.ToList();
            var teachers = _context.Teachers.ToList();

            var viewModel = new ExamViewModel
            {
                People = people,
                Teachers = teachers,
            };

            return View(viewModel);
        }

I’d like to display People.Firstname + " " + People.Surname of all teachers on the dropdown mentioned above, but instead of submitting People.Id I’d like to submit Teachers.Id to Exams.TeacherId

I first tried to displaying a list of the all FirstName before trying displaying FirstName and Surname with the following razor html helper in my Create view but I already failed there as I was only able to access the properties from one single class (Teachers) to use is as dataValueField and dataTextField for new SelectList():

<h2>Plan exam</h2>
@using (Html.BeginForm("Create", "ExamController"))
{
    <div class="form-floating mb-3">
        @Html.DropDownListFor(m => m.Exam.TeacherId, new SelectList(Model.Teachers, "Id", "FirstName"), "-- Please select --", new { @class = "form-control", @placeholder = "Teacher" })
        @Html.LabelFor(m => m.Exam.TeacherId)
    </div>
}

I’m quite new to programming so I’d be very very grateful for any kind of help.

2

Answers


  1. Chosen as BEST ANSWER

    I found a solution:

    1. First I created a second ViewModel with a property Id for Teacher.Id and FullName for Person.FirstName + " " + Person.Surname:
    public class TeacherViewModel
        {
            public int Id { get; set; }
            public string FullName { get ; set; }
        }
    
    1. Then I removed the unnecessary IEnumerable<Person> People from my ExamViewModel and added an IEnumerable<> for Teachers of Type TeacherViewModel:
    public class ExamViewModel
        {
            public Exam Exam { get; set; }
            public IEnumerable<TeacherViewModel> Teachers { get; set; }
        }
    
    1. I created a join as mentionen at step 1, converted it to a list in the new TeacherViewModel:
    public ActionResult Create()
            {
                var teachers = (from t in _context.Teachers
                               join p in _context.People
                               on t.PersonId equals p.Id
                               select new TeacherViewModel
                               {
                                   Id = t.Id,
                                   FullName = p.FirstName + " " + p.Surname,
                               }).ToList();
    
                var viewModel = new ExamViewModel
                {
                    Teachers = teachers,
                };
    
                return View(viewModel);
            }
    
    1. I added a Save() method to the controller:
    public ActionResult Save(Exams exam)
            {
                _context.Exams.Add(exam);
                _context.SaveChanges();
                
                return RedirectToAction("Create", "Exams");
            }
    
    1. Added the submit button to the View and changed the action name beside Html.BeginForm( to Save as it will handle saving the variables from the form.
    @using (Html.BeginForm("Save", "Exams"))
    {
        <div class="form-floating mb-3">
            @Html.DropDownListFor(m => m.Exam.TeacherId, new SelectList(Model.Teachers, "Id", "FullName"), "-- please select --", new { @class = "form-control", @placeholder = "Teacher" })
            @Html.LabelFor(m => m.Exam.TeacherId)
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    }
    

  2. in your viewModel you can only send Exams , but in the query to fetch exams you must make a join to fetch for every exam the teacherID , teacherName , teacherSubname,
    to Learn about that check this :
    here
    or this :
    here

    another thing , in your model ( classes ) definition , i think you have to add a relationship between Exam and Teacher , and between Teacher an People , if you do so it will be easier to fetch only the necessary data , and you will use only one property ( exams ) in your viewModel to send data to the view, to do so check this here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search