ThunD3eR
ThunD3eR

Reputation: 3456

Why does html.dropdownlist set first property option as selected?

I found something really weird and I hope someone can explain this.

I have a dropdownlist :

    <div class="form-group">
        @Html.Label("Roll", new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.DropDownList("UserRole",
           RegistrationHandlers.FilterRoleAssignmentList(),
           "Choose a role",
           new { @class = "form-control", })
        </div>
    </div>

My model contains a huge chunk of properties but the one that is releveant is the enum property :

public OverWatchRoles UserRole { get; set; }

enum:

public enum OverWatchRoles
{
    SuperDeveloper = 0,
    Developer = 1,
    SuperAdministrator = 2,
    Administrator = 3,
    Employee = 4
}

method that populates the dropdownlist:

    public static List<SelectListItem> FilterRoleAssignmentList()
    {
        var user = HttpContext.Current.User.Identity;
        ApplicationDbContext context = new ApplicationDbContext();
        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
        var userRole = UserManager.GetRoles(user.GetUserId());

        List<SelectListItem> roles = new List<SelectListItem>();

        switch (userRole[0])
        {
            case "Developer":
                roles = Enum.GetNames(typeof(OverWatchRoles))
               .Where(f => f != OverWatchRoles.SuperDeveloper.ToString())
               .Select(f => new SelectListItem { Value = f, Text = f, Selected = false }).ToList();
                break;

            case "Administrator":
                roles = Enum.GetNames(typeof(OverWatchRoles))
                .Where(f => f != OverWatchRoles.SuperDeveloper.ToString() && f != OverWatchRoles.Developer.ToString() && f != OverWatchRoles.SuperAdministrator.ToString())
                .Select(f => new SelectListItem { Value = f, Text = f, Selected = false }).ToList();
                break;

            default:
                roles = Enum.GetNames(typeof(OverWatchRoles))
                .Select(f => new SelectListItem { Value = f, Text = f, Selected = false }).ToList();
                break;
        }

        return roles;
    }

Problem:

I found that when I have the name of the dropdownlist = "UserRole" which is the same name as the propetty in the model then the first enum option gets selected by default. when I change the name of the dropdownlist then the default selected value becomes "choose a role".

Why is this happening? and how do i work around it? I'd like to have "choose a role" as the default selected option.

Upvotes: 2

Views: 68

Answers (2)

Vladimirs
Vladimirs

Reputation: 8599

Just adding to CodeCaster's answer. After decompiling Html.DropDownList I can see that at the end it calls SelectExtensions.SelectInternal which uses default value matching property name in case if it fails to get one:

  object defaultValue = allowMultiple ? htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string[])) : htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof (string));
  if (!flag && defaultValue == null && !string.IsNullOrEmpty(name))
    defaultValue = htmlHelper.ViewData.Eval(name);
  if (defaultValue != null)
    selectList = SelectExtensions.GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);

Upvotes: 1

CodeCaster
CodeCaster

Reputation: 151594

It's a non-nullable enum property, so it can't be null. The dropdown will have the model's value selected if it can find a model property with the same name.

So make the model property nullable so it won't have the default value of SuperDeveloper:

public OverWatchRoles? UserRole { get; set; }

Then "Choose a role" will be displayed instead.

Upvotes: 5

Related Questions