Vajda
Vajda

Reputation: 1794

MVC ViewBag dropdown values parameter passing

In database I have table user and student. I generated model using Entity Framework. Since this student class generated only had fields from student, but not form user, I created my own student class with all this fields to use like viewmodel.

I'm using my ViewBag to pass data for dropdown in my view.

ViewBag.Programs = Entities.Programs;

Programs are list study programs at university (like: computer science, law, etc...) So it is 1:N relationship where student can be at just one program, but program can be studied by more students. And in my view I use DropDownFor to make dropdown list from which program is assigned to students when new student is added to database.

<div class="editor-field">
            @Html.DropDownListFor(model => model.ProgramID, ((IEnumerable<SSVN.Models.Program>)ViewBag.Programs).Select(option => new SelectListItem 
       {
        Text = (option == null ? "None" : option.Name), 
        Value = option.ID.ToString(),
        Selected = (Model != null) && (option.ID == Model.ID)
       }), "Choose...")
            @Html.ValidationMessageFor(model => model.ProgramID)
        </div>

Problem is when I click on form submit button, this error appears:

Exception Details: System.ArgumentNullException: Value cannot be null. Parameter name: source

@Html.DropDownListFor(model => model.ProgramID, ((IEnumerable<SSVN.Models.Program>)ViewBag.Programs).Select(option => new SelectListItem 

This part model => model.ProgramID makes error

Well, I tried to simplify problem so that there is no other things that might be unclear to you, so I translated my code to English, since the real code is more on my native language. I think error is there because that is what browser says. Here is code at it's original:

EDIT GET ACTION

// GET: /Unija/Studenti/Izmeni

        public ActionResult Izmeni(int ID)
        {
            ViewBag.StudProgrami = Entities.Studijski_Program;

            SSVN.ModelView.Student student = new SSVN.ModelView.Student();
            SSVN.Models.Student stud = Entities.Students.Single(x => x.ID == ID);
            Korisnik korisnik = Entities.Korisniks.Single(s => s.ID == ID);
            student.ID = korisnik.ID;
            student.KorisnickoIme = korisnik.Korisnicko_Ime;
            student.Lozinka = korisnik.Lozinka;
            student.Ime = stud.Ime;
            student.Prezime = stud.Prezime;
            student.BrojIndeksa = stud.Broj_Indeksa;
            student.TrenutniSemestar = stud.Trenutni_Semestar;
            student.StudijskiProgramID = stud.Studijski_Program_ID;

            return View(student);
        }

EDIT POST ACTION

// POST: /Unija/Studenti/Izmeni

        [HttpPost]
        public ActionResult Izmeni(SSVN.ModelView.Student student)
        {
            if (ModelState.IsValid)
            {
                Korisnik korisnikToUpdate = Entities.Korisniks.Single(x => x.ID == student.ID);
                korisnikToUpdate.Korisnicko_Ime = student.KorisnickoIme;
                korisnikToUpdate.Uloga_ID = Entities.Ulogas.SingleOrDefault(x => x.Naziv == "Student").ID;
                Entities.SaveChanges();

                SSVN.Models.Student studentToUpdate = Entities.Students.Single(x => x.ID == student.ID);
                studentToUpdate.Ime = student.Ime;
                studentToUpdate.Prezime = student.Prezime;
                studentToUpdate.Broj_Indeksa = student.BrojIndeksa;
                studentToUpdate.Trenutni_Semestar = student.TrenutniSemestar;
                studentToUpdate.Studijski_Program_ID = student.StudijskiProgramID;
                Entities.SaveChanges();

                return RedirectToAction("Index");
            }

            return View(student);
        }

VIEW

@model SSVN.ModelView.Student

@{
    ViewBag.Title = "Izmeni";
}

<h2>Dodaj</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Student</legend>

        <div class="hidden-field">
        @Html.HiddenFor(model => model.ID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.KorisnickoIme)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.KorisnickoIme)
            @Html.ValidationMessageFor(model => model.KorisnickoIme)
        </div>
        <input type="hidden" name="Lozinka" value="lozinka" />
        <div class="editor-label">
            @Html.LabelFor(model => model.Ime)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Ime)
            @Html.ValidationMessageFor(model => model.Ime)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Prezime)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Prezime)
            @Html.ValidationMessageFor(model => model.Prezime)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.BrojIndeksa)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.BrojIndeksa)
            @Html.ValidationMessageFor(model => model.BrojIndeksa)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.TrenutniSemestar)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.TrenutniSemestar)
            @Html.ValidationMessageFor(model => model.TrenutniSemestar)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.StudijskiProgramID)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.StudijskiProgramID, ((IEnumerable<SSVN.Models.Studijski_Program>)ViewBag.StudProgrami).Select(option => new SelectListItem 
       {
        Text = (option == null ? "None" : option.Naziv), 
        Value = option.ID.ToString(),
        Selected = (Model != null) && (option.ID == Model.ID)
       }), "Izaberite")
            @Html.ValidationMessageFor(model => model.StudijskiProgramID)
        </div>

        <p>
            <input type="submit" value="Izmeni" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Upvotes: 1

Views: 6925

Answers (2)

Vajda
Vajda

Reputation: 1794

My ModelState was invalid so controller returned the same view. But since in this controller I haven't defined ViewBag lists my DropDownList thrown Null exception.

I just needed to pass those lists via ViewBag.

ViewBag.Katedre = Entities.Katedras;
            ViewBag.Uloge = (System.Data.Objects.ObjectQuery<Uloga>)Entities.Ulogas.Where(x => (x.Naziv == "Profesor" || x.Naziv == "Asistent")).AsEnumerable();

            return View(predavac);

This was problem.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1039498

It seems that Entities.Programs returns null and inside the view when you try to call the .Select extension method on it you get this exception. Or maybe you are putting this DropDownListFor in a view which was rendered from a controller action which doesn't put anything inside ViewBag.Programs.

Personally I would use view models.

So let's start by defining one:

public class ProgramsViewModel
{
    public string ProgramID { get; set; }
    public IEnumerable<SelectListItem> Programs { get; set; }
}

then have a controller action which will take care of populating this view model:

public ActionResult Foo()
{
    var model = new ProgramsViewModel
    {
        Programs = Entities.Programs.Select(p => new SelectListItem
        {
            Value = p.ID,
            Text = p.Name
        })
    };
    return View(model);
}

and inside the view:

@Html.DropDownListFor(
    model => model.ProgramID,     
    new SelectList(Model.Programs, "Value", "Text")
    "Choose..."
)

and if you wanted to preselect some of the options in the dropdown simply set the ProgramID property of your view model to the corresponding value in the controller:

// Preselect the option with value="123"
model.ProgramID = "123";

Upvotes: 1

Related Questions