DropDownListFor - does not select "Selected" value
Asked Answered
A

2

14

Another one of these questions regarding DropDownListFor not selecting the "Selected" value. Here is code:

Model:

public class CreateEditAccountModel
{
    [Required]
    [Display(Name = "Permission")]
    public int PermissionId { get; set; }
    public IEnumerable<SelectListItem> Permissions { get; set; }
}

Controller:

[HttpGet]
[Authorize]
public ActionResult EditAccount(int id)
{
    CreateEditAccountModel model = new CreateEditAccountModel();
    model.Permissions = PermissionsAll();
    return View("CreateEditAccount", model);
}

At this point if I put a break point on return line, the model.Permissions contains proper IEnumerable<SelectListItem> object with multiple items and only one, that has Selected = true.

View:

@using (Html.BeginForm())
{
    @Html.DropDownListFor(m => m.PermissionId, Model.Permissions)
}

Renders:

<select id="PermissionId" name="PermissionId">
    <option value="">-- Select --</option>
    <option value="1">Permission one</option>
    <option value="2">Permission two</option>
</select>

For some reason there is no selected attribute on any of the options and first option is selected.

Any help is appreciated.


UPDATE

It appears it has something to do with this article. To summarize the solution of this article, I need to make sure that the property name (first argument of @html.DropDownList) does not match any existing properties of the model. Can anybody explain why this is the case?

It renders drop down correctly when I write in the view something like this:

@Html.DropDownList("PermissionIdNotMatching", Model.Permissions)

However, it does not make any logical sense to do it since I actually want binder to be able to match the name of the select element to the model property. Otherwise I'd have to manually grab the value like this: Request.Form["PermissionIdNotMatching"];

Anybody have any thoughts?


SOLUTION

See accepted answer and the first comment to it.

Avent answered 23/3, 2012 at 1:13 Comment(1)
The value of PermissionId should be equal to SelectListItem.Value for which Selected = true. Try model.PermissionId = Convert.ToInt32(lst.First(t => t.Selected).Value); I also faced same problem as you did, surprisingly the value was getting selected when editing, from there I figured that the PermissionId should have the same value that is for the selected SelectListItem's value. Worked for me.Phaih
H
8

Ok, let's discuss about your example, when PermissionId was int. You posted model of type CreateEditAccountModel to view. When you created this model, PermissionId equal 0 (default value of int). And DropDownListFor in view get this value. Therefore you had no selected values. When you used string type, default value of PermissionId was null, therefore `DropDownListFor taken default value of SelectList.

In this case it's better to use int? or Nullable<int> type for PermissionId.

Herring answered 12/11, 2013 at 12:14 Comment(2)
your explanation is relevant. Way back, when I asked this question I didn't understand that DropDownListFor will first evaluate the value of PermissionId and if it's not null, it will make that value selected. Otherwise it would take into account Model.PermissionsAvent
This may and may not have to do with question but it may be useful to someone when you let's say create a List<SelectListItem> from linq to entities and convert Int to string Value make sure to trim if you are using SqlFunctions.StringConvert cause it will not render selected = true for preselected value. Not trimming is causing dropdown to have values like so: value = " 1".Andante
I
4

When you use @Html.DropDownListFor(m => m.PermissionId, Model.Permissions), please ensure the PermissionId is already set in your Model - that is the selected item / id. In addition, the model contains a 'selected' attribute:

var query = DatabaseContexts.Select(
            c => new SelectListItem
            {
                Value = c.Key,
                Text = c.Value,
                Selected = c.Key == currentUsed
            });

 PermissionId = that want to select;
 Permissions = query.AsEnumerable();

UPDATE:

here is a full sample of HttpGet:

In HomeController.cs:

[HttpGet]
public ActionResult EditAccount(int id)
{
    CreateEditAccountModel model = new CreateEditAccountModel();

    var permissionsAll = new List<SelectListItem>
         {
             new SelectListItem
                 {
                     Value = "",
                     Text = "--please select--",
                     Selected = false
                 },
             new SelectListItem
                 {
                     Value = "1",
                     Text = "Permission one",
                     Selected = true
                 },
             new SelectListItem
                 {
                     Value = "2",
                     Text = "Permission two",
                     Selected = false
                 }
         };
    model.PermissionId = 1; //add this line
    model.Permissions = permissionsAll; // PermissionsAll();// -- get data from services or anywhere....
    return View("EditAccount", model);
}

CreateEditAccountModel.cs:

public class CreateEditAccountModel
{
    [Required]
    [Display(Name = "Permission")]
    public int PermissionId { get; set; }
    public IEnumerable<SelectListItem> Permissions { get; set; }

}

EditAccount.cshtml:

@using MvcApplication1.Models
@model CreateEditAccountModel
@{
   ViewBag.Title = "EditAccount";
 }

<h2>EditAccount</h2>
@using (Html.BeginForm())
{
   @Html.DropDownListFor(m => m.PermissionId, Model.Permissions)
}

Run the application and go to /home/editaccount/1, the dropdown will select "Permission one" by default.

I think the PermissionId must be type 'string' is, System.Web.Mvc.SelectedListItem.Value is 'string'

If you would like to do something when user selected item in the dropdown list, you may need [HttpPost].

BTW: this link is useful to you?

Impudence answered 23/3, 2012 at 2:59 Comment(7)
PermissionId was actually set. I originally copied wrong set of properties from the model. Please review again.Avent
in controller: CreateEditAccountModel model = new CreateEditAccountModel(); model.Permissions = PermissionsAll(); model.PermissionId = 1; /*selected id */ return View("CreateEditAccount", model); in view: @Html.DropDownListFor(m => m.PermissionId, Model.Permissions);Impudence
xoyoja, why would you assign a value to it on HttpGet? In any case the variable value should not affect the drop down list since it's just a variable that will hold selected value. I still tried it and it didn't help. Thanks for trying!Avent
xoyoja, thanks for help. Assigning model.PermissionId = 1; did not help. I have found a solution to the problem though and it was the type of PermissionId being int. I have updated my question with the UPDATE section, which shows some thinking in progress and the SOLUTION section. The ling regarding SelectList isn't working on HttpPost is irrelevant since all I have it HttpGetAvent
@Dmitry, Just create an empty asp.net mvc3 razor application in vs2010, paste my code from "update" section, it could work. BTW: Regarding the question 'why PermissionId variable must be of type string in order for DropDownListFor to work', If you don't like the method of DropDownListFor, you can create your own extension method of "HtmlHelper.DropDownListFor", it's quite straight forward. All the components of ASP.NET MVC framework are designed so that they can be easily replaced or customized.Impudence
I know your code will work. But it will work not because you set model.PermissionId = 1, but because you have Selected = true on SelectListItem with Value = 1. Just a coincident. That coupled with the fact that your values are strings. I know I can do my custom extension, but I'd think that any scalar types should be figured out by the model binder.Avent
If you don't set model.PermissionId = 1, even you have Selected = true on SelectListItem with Value = 1, it won't work. please test. BTW: Recommend to use DropDownList: @using (Html.BeginForm()) { var items = new List<SelectListItem>(); items.Add(new SelectListItem { Text = "a", Value = "0" }); items.Add(new SelectListItem { Text = "b", Value = "1" }); items.Add(new SelectListItem { Text = "c", Value = "2", Selected = true }); items.Add(new SelectListItem { Text = "d", Value = "3" }); @Html.DropDownList("abc", @items) }Impudence

© 2022 - 2024 — McMap. All rights reserved.