Enlazar DropDownList de la base de datos

Nov 24 2020

Estoy construyendo una vista que mostrará datos tabulares basados ​​en selecciones de dos listas desplegables, la primera que selecciona departamentos se completa desde la base de datos. El segundo es una lista desplegable estática para "Año", que todavía no tengo. Hay respuestas a preguntas similares, pero las he mirado y he probado todo. Llegué al punto en que obtengo una excepción nula en la vista donde creé el marcado para la lista desplegable.

Ver:

Departamentos regresa como nulo. Soy nuevo en MVC y reconstruí esto a partir de ejemplos en línea . Supongo que mi modelo está mal.

@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; }
}

Controlador:

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

Clase de repositorio:

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;
}

Respuestas

1 JamshaidK. Nov 24 2020 at 06:13

Entonces, está guardando los valores en la SelectedDepartmentpropiedad y accediendo a la Departmentslista. Que nunca se inicializa, por lo que obviamente lo sería null.

Modifica tu GetBudgetsActualsmétodo así:

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;
}

Y así es como debería verse su Vista:

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

Fíjate, nos deshicimos del foreachbucle. Necesitamos DropDownListFor()que se llame al método solo una vez.


ACTUALIZAR

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.
}