Petko Xyz
Petko Xyz

Reputation: 31

DropDownList and ViewData

In my controller I have:

        Category x = new Category(1, "one", 0);
        Category y = new Category(2, "two", 1);
        Category z = new Category(3, "three", 1);
        List<Category> categories = new List<Category>();
        categories.Add(x);
        categories.Add(y);
        categories.Add(z);
        ViewData["categories"] = categories;

And in my view I have:

    <%= Html.DropDownList("categories")%>

But I have an error:

The ViewData item that has the key 'categories' is of type 'System.Collections.Generic.List`1[[Category, MvcApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' but must be of type 'IEnumerable'.

Uggggghhh how to resolve this?

Upvotes: 1

Views: 5203

Answers (5)

Brendan Vogt
Brendan Vogt

Reputation: 26018

The better way to do this is to create a view model for each view/page, populate it with data (if required) and return this to the view/page. Never return your domain model to the view/page.

The code provided below is for ASP.NET MVC3, but it is easy to relate to your situation

Lets assume you are creating a new product which needs to be in a category (displayed in a select list), so you will need a Create view/page and action method. I would create the following view model:

public class ProductCreateViewModel
{
     // Include other properties if needed, these are just for demo purposes

     public string Name { get; set; }
     public string SKU { get; set; }
     public string LongDescription { get; set; }

     // This is the unique identifier of your category,
     // i.e. foreign key in your product table
     public int CategoryId { get; set; }
     // This is a list of all your categories populated from your category table
     public IEnumerable<Category> Categories { get; set; }
}

Category class:

public class Category
{
     public int Id { get; set; }
     public string Name { get; set; }
}

In your Create view you would have the following:

@model MyProject.ViewModels.ProductCreateViewModel

@using (Html.BeginForm())
{
     <table>
          <tr>
               <td><b>Category:</b></td>
               <td>
                    @Html.DropDownListFor(x => x.CategoryId,
                         new SelectList(Model.Categories, "Id", "Name", Model.CategoryId),
                         "-- Select --"
                    )
                    @Html.ValidationMessageFor(x => x.CategoryId)
               </td>
          </tr>
     </table>

     <!-- Add other HTML controls if required and your submit button -->
}

Your Create action methods:

public ActionResult Create()
{
     ProductCreateViewModel viewModel = new ProductCreateViewModel
     {
          // Here you do a database call to populate your dropdown
          Categories = categoryService.GetAllCategories()
     };

     return View(viewModel);
}

Upvotes: 0

Admiral Ackbar
Admiral Ackbar

Reputation: 64

I know this is old but in case someone is looking for the answer

supposing that Categories have and Id, and Name and the current CategoryId is in the model

@Html.DropDownListFor(m => m.CategoryId, new SelectList((IEnumerable)ViewData["categories"], "Id", "Name"))

Upvotes: 0

Sunil
Sunil

Reputation: 2905

Use Jquery Ajax + JSON is to fill the dropdown. This will result in better responsive web page.

It is so simple. All you have to do is, add a new action of returntype JSONResult and moves the dropdown loading codes to there.

In Controller Class: Create a new action:

public JsonResult FillDropDown()
        {
            Category x = new Category(1, "one", 0);
            Category y = new Category(2, "two", 1);
            Category z = new Category(3, "three", 1);
            List<Category> categories = new List<Category>();
            categories.Add(x);
            categories.Add(y);
            categories.Add(z);

            return Json(categories,JsonRequestBehavior.AllowGet);
        }

In View Page: Add Jquery code for load data from server.

<script type="text/javascript">
    $(document).ready(function () 
    {
        var _selbxTest = $('#selbxTest'); //Get dropdownlistbox 
        $.getJSON(
            '@Url.Action("FillDropDown","Home")', //Provide JsonResultActionName, ControllerName
             {},
                function (_recdData) {
                    //Update dropdownListBox here
                    _selbxTest.append($('<option></option>').val(0).html('Select')); 
                    $.each(_recdData, function (key, value) {
                        _selbxTest.append($('<option></option>').val(value.value).html(value.text));
                    });
                });
    });
</script>

Finally add a simple selectbox in your view page instead of Html.DropDownList()

<div>
        <select id="selbxTest"></select>
</div>

Hope this will help you. Thanks.

Upvotes: 0

Rapha&#235;l Althaus
Rapha&#235;l Althaus

Reputation: 60493

You can maybe try

ViewData["categories"] = new SelectList(categories, "Id", "Name");

(assuming Category has a Name and and Id Field)

Then you can add logic to keed selected value.

EDIT : cause your error message is not complete, if I'm not wrong : it's asking for an IEnumerable<SelectListItem>

Upvotes: 3

DOK
DOK

Reputation: 32831

In the line before you create the ViewData item, you can convert the List<T> to an IEnumerable<T>

IEnumerable<Category> cat = categories;
ViewData["categories"] = cat;

Upvotes: 0

Related Questions