59

Here is my model:

public class NewsCategoriesModel {
    public int NewsCategoriesID { get; set; }        
    public string NewsCategoriesName { get; set; }
}

My controller:

public ActionResult NewsEdit(int ID, dms_New dsn) {
    dsn = (from a in dc.dms_News where a.NewsID == ID select a).FirstOrDefault();
    var categories = (from b in dc.dms_NewsCategories select b).ToList();
    var selectedValue = dsn.NewsCategoriesID;
    SelectList ListCategories = new SelectList(categories, "NewsCategoriesID", "NewsCategoriesName",selectedValue);

    // ViewBag.NewsCategoriesID = new SelectList(categories as IEnumerable<dms_NewsCategory>, "NewsCategoriesID", "NewsCategoriesName", dsn.NewsCategoriesID);
    ViewBag.NewsCategoriesID = ListCategories;
    return View(dsn);
}

And then my view:

@Html.DropDownList("NewsCategoriesID", (SelectList)ViewBag.NewsCategoriesID)

When i run, the DropDownList does not select the value I set.. It is always selecting the first option.

Necreaux
  • 9,451
  • 7
  • 26
  • 43
Raito Light
  • 627
  • 2
  • 6
  • 8
  • 10
    Your model and select list have the same name, you can't do that. See my DDL tutorial http://www.asp.net/mvc/tutorials/javascript/working-with-the-dropdownlist-box-and-jquery/using-the-dropdownlist-helper-with-aspnet-mvc and http://blogs.msdn.com/b/rickandy/archive/2012/01/09/cascasding-dropdownlist-in-asp-net-mvc.aspx – RickAndMSFT Mar 20 '12 at 16:17
  • @RickAnd-MSFT: I believe your comment deserved be considered as the accepted answer. thanks – Vahid Ghadiri Feb 28 '14 at 20:18

10 Answers10

105

You should use view models and forget about ViewBag Think of it as if it didn't exist. You will see how easier things will become. So define a view model:

public class MyViewModel
{
    public int SelectedCategoryId { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; } 
}

and then populate this view model from the controller:

public ActionResult NewsEdit(int ID, dms_New dsn)
{
    var dsn = (from a in dc.dms_News where a.NewsID == ID select a).FirstOrDefault();
    var categories = (from b in dc.dms_NewsCategories select b).ToList();

    var model = new MyViewModel
    {
        SelectedCategoryId = dsn.NewsCategoriesID,
        Categories = categories.Select(x => new SelectListItem
        {
            Value = x.NewsCategoriesID.ToString(),
            Text = x.NewsCategoriesName
        })
    };
    return View(model);
}

and finally in your view use the strongly typed DropDownListFor helper:

@model MyViewModel

@Html.DropDownListFor(
    x => x.SelectedCategoryId,
    Model.Categories
)
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 49
    Nothing wrong with using ViewBag to contain the SelectList - the MVC scaffolding mechanism does that. His problem was using the same name for the model and the selectlist. – RickAndMSFT Mar 20 '12 at 16:20
  • 3
    this answer completely missed the problem. @RickAndMSFT, thanks for the actual solution – Liam Aug 22 '12 at 11:20
  • 7
    @Liam, you call something that uses ViewBag *an actual solution*? I wouldn't :-) Cheers anyway. – Darin Dimitrov Aug 22 '12 at 11:25
  • 1
    @Darin Dimitrov: It's their for a reason! You call cluttering up your model with SelectListItems an actual solution?! It's also less efficient to pass objects back and forwards in this way. It needs serialising and it takes up bandwidth on the wire. Are you going to use this data when you post the form? No, don't put it in the Model then. – Liam Aug 22 '12 at 11:29
  • that sounds overly preachy by the way, I take your point, I just don't agree! :) – Liam Aug 22 '12 at 11:31
  • I just had this problem and decided to add a solution based on @RickAndMSFT's comment. I think there is value to building a good view model but this answer does't specifically address the problem. – Uriah Blatherwick Oct 11 '12 at 02:12
  • If i have more than one Dropdown how could i use this model? – A Coder May 10 '14 at 17:38
  • so using the ViewBag for selectlists is "bad practice" then?! – niico Sep 17 '16 at 23:25
  • Grear answer! A much better practice than using viewbag – ammad khan Aug 03 '20 at 07:33
22

just in case someone comes with this question, this is how I do it, please forget about the repository object, I'm using the Repository Pattern, you can use your object context to retrieve the entities. And also don't pay attention to my entity names, my entity type Action has nothing to do with an MVC Action.

Controller:

ViewBag.ActionStatusId = new SelectList(repository.GetAll<ActionStatus>(), "ActionStatusId", "Name", myAction.ActionStatusId);

Pay attention that the last variable of the SelectList constructor is the selected value (object selectedValue)

Then this is my view to render it:

<div class="editor-label">
   @Html.LabelFor(model => model.ActionStatusId, "ActionStatus")
</div>
<div class="editor-field">
   @Html.DropDownList("ActionStatusId")
   @Html.ValidationMessageFor(model => model.ActionStatusId)
</div> 

I think it is pretty simple, I hope this helps! :)

Alfonso Muñoz
  • 1,609
  • 17
  • 24
  • Thanks Ben. Honestly I think that my solution is the simplest one of these available. Just create the SelectList and at the same time pass the selected value in the constructor of SelectList. Glad it helped you :) – Alfonso Muñoz Mar 28 '12 at 23:00
  • This worked great for me when I found myself in a situation where I had a list of my viewmodel type and needed to do this problem multiple times on the same page in a loop. Much cleaner I think than having to re-tool my view models. – sovemp Jun 12 '13 at 04:43
16

I drilled down the formation of the drop down list instead of using @Html.DropDownList(). This is useful if you have to set the value of the dropdown list at runtime in razor instead of controller:

<select id="NewsCategoriesID" name="NewsCategoriesID">
    @foreach (SelectListItem option in ViewBag.NewsCategoriesID)
    {
        <option value="@option.Value" @(option.Value == ViewBag.ValueToSet ? "selected='selected'" : "")>@option.Text</option>

    }
</select>
Shadi Alnamrouti
  • 11,796
  • 4
  • 56
  • 54
8

Well its very simple in controller you have somthing like this:

-- Controller

ViewBag.Profile_Id = new SelectList(db.Profiles, "Id", "Name", model.Profile_Id);

--View (Option A)

@Html.DropDownList("Profile_Id")

--View (Option B) --> Send a null value to the list

@Html.DropDownList("Profile_Id", null, "-- Choose --", new {  @class = "input-large" })
Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
CXRom
  • 103
  • 1
  • 5
  • Can please you explain what is the difference between using `null` instead of `ViewBag.Profile_Id as SelectList` – nishanthan Jan 09 '15 at 10:28
6

Replace below line with new updated working code:

@Html.DropDownList("NewsCategoriesID", (SelectList)ViewBag.NewsCategoriesID)

Now Implement new updated working code:

@Html.DropDownListFor(model => model.NewsCategoriesID, ViewBag.NewsCategoriesID as List<SelectListItem>, new {name = "NewsCategoriesID", id = "NewsCategoriesID" })
Yasel
  • 2,920
  • 4
  • 40
  • 48
Anjan Kant
  • 4,090
  • 41
  • 39
5

I want to put the correct answer in here, just in case others are having this problem like I was. If you hate the ViewBag, fine don't use it, but the real problem with the code in the question is that the same name is being used for both the model property and the selectlist as was pointed out by @RickAndMSFT

Simply changing the name of the DropDownList control should resolve the issue, like so:

@Html.DropDownList("NewsCategoriesSelection", (SelectList)ViewBag.NewsCategoriesID)

It doesn't really have anything to do with using the ViewBag or not using the ViewBag as you can have a name collision with the control regardless.

4

I prefer the lambda form of the DropDownList helper - see MVC 3 Layout Page, Razor Template, and DropdownList

If you want to use the SelectList, then I think this bug report might assist - http://aspnet.codeplex.com/workitem/4932

Community
  • 1
  • 1
Stuart
  • 66,722
  • 7
  • 114
  • 165
2

code bellow, get from, goes

Controller:

int DefaultId = 1;
ViewBag.Person = db.XXXX
        .ToList()
        .Select(x => new SelectListItem {
            Value = x.Id.ToString(),
            Text = x.Name,
            Selected = (x.Id == DefaultId)
        });

View:

@Html.DropDownList("Person")

Note: ViewBag.Person and @Html.DropDownList("Person") name should be as in view model

user1855805
  • 137
  • 1
  • 1
  • 9
  • This solution worked for me, as I did not have an option to use DropdownListFor as I was making dropdown dynamically on run time. Thanks. – anu Apr 06 '17 at 20:30
1

To have the IT department selected, when the departments are loaded from tblDepartment table, use the following overloaded constructor of SelectList class. Notice that we are passing a value of 1 for selectedValue parameter.

ViewBag.Departments = new SelectList(db.Departments, "Id", "Name", "1");
Azarsa
  • 1,278
  • 3
  • 27
  • 37
0

For anyone that dont want to or dont make sense to use dropdownlistfor, here is how I did it in jQuery with .NET MVC set up.

  1. Front end Javascript -> getting data from model:
    var settings = @Html.Raw(Json.Encode(Model.GlobalSetting.NotificationFrequencySettings)); 

    SelectNotificationSettings(settings);

    function SelectNotificationSettings(settings) {
                $.each(settings, function (i, value) {
                    $("#" + value.NotificationItemTypeId + " option[value=" + value.NotificationFrequencyTypeId + "]").prop("selected", true);
                });
    }
  1. In razor html, you going to have few dropdownlist
 @Html.DropDownList(NotificationItemTypeEnum.GenerateSubscriptionNotification.ToString,
    notificationFrequencyOptions, optionLabel:=DbRes.T("Default", "CommonLabels"),
    htmlAttributes:=New With {.class = "form-control notification-item-type", .id = Convert.ToInt32(NotificationItemTypeEnum.GenerateSubscriptionNotification)})

And when page load, you js function is going to set the selected option based on value that's stored in @model.

Cheers.

Lucas
  • 1
  • 1