Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET CORE MVC SelectList from a collection of Objects

So I have these 2 classes representing tables in a local db using ef core migration in an asp.net core app

public class Teacher
{
    public int ID { get; set; }

    public string FistName { get; set; }

    public string LastName { get; set; }

    public Class Class { get; set; }

    public string FullName
    {
        get
        {
            return $"{LastName} {FistName}";
        }
    }

    public override string ToString()
    {
        return FullName;
    }
}

and

public class Class
{
    public int ID { get; set; }

    public int TeacherID { get; set; }

    public string Name { get; set; }


    public Teacher Teacher { get; set; }

    public ICollection<Student> Students { get; set; }
}

I want to add in my classes controller the functionality to create a new instance of the "Class" class by typing out a name in a textbox and selecting a teacher from a dropdownlist.

Here are my create http get & post methods

    public IActionResult Create()
    {
        var teachers = from s in _context.Teachers
                           where s.Class == null
                           select s;

        ViewData["Teachers"] = new SelectList(teachers.ToList());
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(Class @class)
    {
        if (ModelState.IsValid)
        {
            @class.TeacherID = @class.Teacher.ID;
            _context.Add(@class);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View("Index");
    }

and the form for submitting user-typed data

<form asp-action="Create">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Teacher" class="control-label"></label>
            <select asp-for="Teacher" class ="form-control" asp-items="ViewBag.Teachers"></select>
        </div>
        <div class="form-group">
            <label asp-for="Name" class="control-label"></label>
            <input asp-for="Name" class="form-control" />
            <span asp-validation-for="Name" class="text-danger"></span>
        </div>
        <div class="form-group">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </form>

I can see the right data in the dropdown list but for some reason inside the POST method @class.Teacher is null. What am I doing wrong?

like image 386
Codrin Muntean Avatar asked Jan 16 '19 19:01

Codrin Muntean


2 Answers

First update your Create GET method as follows:

public async Task<IActionResult> Create()
{
    var teachers = await _context.Teachers.Where(t => t.Class == null).ToListAsync();
    ViewData["Teachers"] = new SelectList(teachers,"ID","FullName");
    return View();
}

Then write your FormGroup for select list as follows:

<div class="form-group">
     <label asp-for="TeacherID" class="control-label">Teacher</label>
     <select asp-for="TeacherID" class ="form-control" asp-items="ViewBag.Teachers">
     </select>
     <span asp-validation-for="TeacherID" class="text-danger"></span>
</div>

Now update your Create POST method as follows:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Class @class)
{
    if (ModelState.IsValid)
    {
        _context.Classes.Add(@class); // now your @class is containing the `TeacheID` value selected from drop-down.
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View("Index");
}

Now everything should work fine!

like image 84
TanvirArjel Avatar answered Oct 19 '22 01:10

TanvirArjel


Make the following changes

Create http get method , view SelectList Class , set ID to the dataValueFieldof the selectList and set FullNameto the dataTextFieldof selectList

 public IActionResult Create()
    {
        var teachers = from s in _context.Teacher
                       where s.Class == null
                       select s;

        ViewData["Teachers"] = new SelectList(teachers.ToList(),"ID","FullName");
        return View();
    }

The select tag in the form

<select asp-for="TeacherID" class="form-control" asp-items="ViewBag.Teachers"></select>
like image 25
Xueli Chen Avatar answered Oct 19 '22 02:10

Xueli Chen