1
votes

I'm using ASP.NET MVC Core, Entity Framework Core and SQL Server. I have the following Models and Controllers listed below. Everything works fine, I'm able to retrieve the data from my Database to my DropDownList Controls using fine.

What I would like to know if someone could assist me with is there a better way to retrieve the data in the "public IActionResult Create()" that I have now within the EmployeeController?

I would like if possible but not sure how to, create 2 Methods called public IActionResult DeptData() and IActionResult BldgData() to retrieve the data to those Methods and then pass the returned data to the public IActionResult Create() Method of the EmployeeController rather than how I have it now.

Employee Model:

    public class Employee
{
    [Key]
    public int EmpId { get; set; }
    [Required]
    public string EmpFirstName { get; set; }
    [Required]
    public string EmpLastName { get; set; }

    public int DeptId { get; set; }
    public Department Department { get; set; }

    public int BldgId { get; set; }
    public Building Building { get; set; }
}

EmployeeController:

public class EmployeeController : Controller
{
    private DataEntryContext _context;

    public EmployeeController(DataEntryContext context)
    {
        _context = context;
    }

    // GET: /<controller>/
    public IActionResult Index()
    {
        return View(_context.Employees.ToList());
    }

    public string RetrieveDept()
    {
        var getDeptTitle = _context.Departments.ToList();
        SelectList Deptlist = new SelectList(getDeptTitle, "DeptId", "DeptTitle");
        ViewBag.DeptListName = Deptlist;

        return View(Create);
    }

    public IActionResult Create()
    {
        var getDeptTitle = _context.Departments.ToList();
        SelectList Deptlist = new SelectList(getDeptTitle, "DeptId", "DeptTitle");
        ViewBag.DeptListName = Deptlist;

        var getBldgTitle = _context.Buildings.ToList();
        SelectList Bldglist = new SelectList(getBldgTitle, "BldgId", "BldgName");
        ViewBag.BldgListName = Bldglist;

        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create(Employee employee)
    {
        if (ModelState.IsValid)
        {
            _context.Employees.Add(employee);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(employee);
    }
}

Employee Create View:

<form asp-controller="employee" asp-action="Create" method="post" class="form-horizontal" role="form">
<div class="form-horizontal">
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="EmpFirstName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="EmpFirstName" class="form-control" />
            <span asp-validation-for="EmpFirstName" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="EmpLastName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="EmpLastName" class="form-control" />
            <span asp-validation-for="EmpLastName" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="DeptId" class="col-md-2 control-label"></label>
        <div class="col-md-10">      
            <select asp-for="DeptId" asp-items="@ViewBag.DeptListName" class="form-control"></select>  
            <span asp-validation-for="DeptId" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="BldgId" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <select asp-for="BldgId" asp-items="@ViewBag.BldgListName" class="form-control"></select>
            <span asp-validation-for="BldgId" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>

2
both of the dropdowns could be partial views. You just need to pass the listsRoyal Bg

2 Answers

1
votes

One thing you can do is to wrap the code to get the items needed for the dropdown to a separate method which can be called from other action methods.

public IActionResult Create()
{
    ViewBag.DeptListName = GetDepartments();
    // Do the same for your other dropdown also
    return View();
 }
 private IEnumerable<SelectListItem> GetDepartments()
 {
      return context.Departments
                    .Select(s=> new SelectListItem { 
                                                     Value=s.DeptId.ToString(),
                                                     Text=s.DeptTitle })
                    .ToList();
 }

I personally prefer to avoid ViewBag and ViewData and use a strongly typed view model to pass these data to the view. Here is a post explaining how to do it if you are interested.

0
votes

I would recommend using partial views. Each of them with the relevant dropdowns.

First of all, I do not recommend using ViewBag, but strongly-typed views. So your master view will need to accept MasterCreateViewModel and you need to create one that has both Buildings and Departments

class MasterCreateViewModel
{
    public List<Department> Departments { get; set; }
    public List<Building> Buildings { get; set; }
}

And your Master Create should return the view with this ViewModel.

public IActionResult Create()
{
    var getDeptTitle = _context.Departments.ToList();
    var getBldgTitle = _context.Buildings.ToList();
    var viewModel = new MasterCreateViewModel()
                     {
                             Departments = getDeptTitle,
                             Buildings = getBldgTitle 
                     }

    return View(viewModel);
}

Then you need two actions that return partial views with the relevant dropdowns. E.g.

public IActionResult CreateDepartmentsPartial(List<Department> departments)
{
    return PartialView("CreateDepartmentsPartial", departments);
}

And, the partial view as well:

<div class="form-group">
    <label asp-for="DeptId" class="col-md-2 control-label"></label>
    <div class="col-md-10">      
        <select asp-for="DeptId" asp-items="@Model" class="form-control"></select>  
        <span asp-validation-for="DeptId" class="text-danger"></span>
    </div>
</div>

Then you need to Invoke the partial view with the relevant model:

 <div class="form-group">
        <label asp-for="EmpLastName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="EmpLastName" class="form-control" />
            <span asp-validation-for="EmpLastName" class="text-danger"></span>
        </div>
    </div>
@Html.RenderPartial("CreateDepartmentsPartial", Model.Departments)

P.S.: ASP.NET Core has also asynchronous partial rendering.