Wiązanie DropDownList z bazy danych

Nov 24 2020

Buduję widok, który będzie wyświetlał dane tabelaryczne na podstawie wyborów z dwóch list rozwijanych, z których pierwsza, która wybiera działy, jest wypełniana z bazy danych. Druga to statyczna lista rozwijana dla „roku”, której jeszcze nie mam. Są odpowiedzi na podobne pytania, ale spojrzałem na nie i spróbowałem wszystkiego. Dotarłem do punktu, w którym otrzymuję zerowy wyjątek w widoku, w którym utworzyłem znaczniki dla listy rozwijanej.

Widok:

Działy powracają jako zerowe. Jestem nowy w MVC i zebrałem to razem z przykładów online . Domyślam się, że mój model jest zły.

@model IEnumerable<BudgetDemo.Models.BudgetsActualsViewModel>

@foreach (var item in Model)
{
    @Html.DropDownListFor(m => item.Departments, 
        new SelectList(item.Departments.Select(x => x.Text)))
}

ViewModel:

public class BudgetsActualsViewModel
{
    [Display(Name = "Cost Center/Department")]
    [Required(ErrorMessage = "Cost Center/Department is required.")]
    [StringLength(62)]
    public string SelectedDepartment { get; set; }
    public IEnumerable<SelectListItem> Departments { get; set; }
}

Kontroler:

public ActionResult GetBudgetsActuals()   
{
    repo = new BudgetDemoRepository();
    ModelState.Clear();
    return View(repo.GetBudgetsActuals());
}

Klasa repozytorium:

public List<BudgetsActualsViewModel> GetBudgetsActuals()  
{
    ...
    List<BudgetsActualsViewModel> budgetsActualsList = new List<BudgetsActualsViewModel>();
    // Query returning correct data from DB here

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
        budgetsActualsList.Add(
            new BudgetsActualsViewModel
             {
                 SelectedDepartment = ds.Tables[0].Rows[i]["Department"].ToString()
             }
        );
    }
    return budgetsActualsList;
}

Odpowiedzi

1 JamshaidK. Nov 24 2020 at 06:13

Tak więc zapisujesz wartości we SelectedDepartmentwłaściwości i uzyskujesz dostęp do Departmentslisty. Który nigdy nie jest inicjowany, więc oczywiście tak będzie null.

Zmodyfikuj swoją GetBudgetsActualsmetodę w następujący sposób:

public BudgetsActualsViewModel GetBudgetsActuals()  
{
    ...
    BudgetsActualsViewModel budgetsActuals = new BudgetsActualsViewModel(){ Departments = new List<SelectListItem>() };
    // Query returning correct data from DB here

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
        budgetsActuals.Departments
                      .Add(new SelectListItem 
                          { 
                              Text = ds.Tables[0].Rows[i]["Department"].ToString(), 
                              Value = ds.Tables[0].Rows[i]["YourRowId"].ToString() 
                          });
    }
    return budgetsActuals;
}

A tak powinien wyglądać Twój widok:

@model BudgetDemo.Models.BudgetsActualsViewModel
@Html.DropDownListFor(m => m.SelectedDepartment, Model.Departments))

Zauważ, że pozbyliśmy się foreachpętli. Potrzebujemy DropDownListFor()wywołania metody tylko raz.


AKTUALIZACJA

public class BudgetsActualsViewModel
{
    [Display(Name = "Cost Center/Department")]
    [Required(ErrorMessage = "Cost Center/Department is required.")]
    [StringLength(62)]
    public string SelectedDepartment { get; set; }
    public List<SelectListItem> Departments { get; set; } // Modify it to list instead IEnumerable.
}