user2439521
user2439521

Reputation:

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key <x>

I have a page with two DropDownLists and two TextFields. Both DropDownLists are populated from mySQl database tables using ADO.Net Entity Model in Microsoft Visual Studio 2015. Controller

    [HttpGet]
    public ViewResult MngBranch()
    {
        DbModel pdb = new DbModel();
        ViewBag.type = new SelectList(pdb.branchtypes, "Id", "Type");
        ViewBag.name = new SelectList(pdb.companies, "IdCompany", "CompanyName");
        return View();
    }

    [HttpPost]
    public ViewResult MngBranch(Branch branch)
    {
        if (ModelState.IsValid)
        {
            ViewBag.Name = branch.BranchName;
            return View("BranchSaved");
        }
        else
        {
            return View();
        }
    }

View

@using (Html.BeginForm())
        {
        @Html.ValidationSummary()
        <p>Company Name: @Html.DropDownListFor(x => x.CompanyName, (SelectList)ViewBag.name,"Choose an option")</p>
        <p>Branch Name: @Html.TextBoxFor(x => x.BranchName)</p>
        <p>Branch Code: @Html.TextBoxFor(x => x.BranchCode)</p>
        <p>Branch Type:@Html.DropDownListFor(x => x.BranchType, (SelectList)ViewBag.type, "Choose an option")
        </p>

For some reason in this particular view I get the error:

There is no ViewData item of type 'IEnumerable<SelectListItem> ' that has the key 'CompanyName'.

when validation fails.

Upvotes: 0

Views: 92

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1038830

The error message is pretty straightforward. You are using ViewData instead of the view model. So you cannot possibly expect to be able to use strongly typed helpers such as Html.DropDownListFor in your views. You should rather create an instance of your view model in the controller action that will be passed to the view.

So as always start by writing a proper view model:

public class MyViewModel
{
    [Required]
    public string CompanyName { get; set; }
    [Required]
    public string BranchType { get; set; }
    public string BranchName { get; set; }
    public string BranchCode { get; set; }
    public IEnumerable<SelectListItem> CompanyNames { get; set; }
    public IEnumerable<SelectListItem> BranchTypes { get; set; }
}

Now that you've got the view model just populate it:

[HttpGet]
public ActionResult MngBranch()
{
    DbModel pdb = new DbModel();
    var model = new MyViewModel();
    model.BranchTypes = new SelectList(pdb.branchtypes, "Id", "Type");
    model.CompanyNames = new SelectList(pdb.companies, "IdCompany", "CompanyName");
    return View(model);
}

[HttpPost]
public ViewResult MngBranch(MyViewModel model)
{
    if (ModelState.IsValid)
    {
        return View("BranchSaved");
    }
    else
    {
        DbModel pdb = new DbModel();
        // You need to repopulate the drop down box values
        // if you are going to redisplay the same view
        model.BranchTypes = new SelectList(pdb.branchtypes, "Id", "Type");
        model.CompanyNames = new SelectList(pdb.companies, "IdCompany", "CompanyName");
        return View(model);
    }
}

and now all that's left is to ensure that your view is strongly typed to this view model (rather than your domain model):

@model MyViewModel

@using (Html.BeginForm())
{
    @Html.ValidationSummary()
    <p>
        Company Name: 
        @Html.DropDownListFor(x => x.CompanyName, Model.CompanyNames, "Choose an option")
    </p>
    <p>
        Branch Name: 
        @Html.TextBoxFor(x => x.BranchName)
    </p>
    <p>
        Branch Code: 
        @Html.TextBoxFor(x => x.BranchCode)
    </p>
    <p>
        Branch Type:
        @Html.DropDownListFor(x => x.BranchType, Model.BranchTypes, "Choose an option")
    </p>
}

As you can see it's much easier to work with view models in ASP.NET MVC.

Upvotes: 2

Related Questions