None
None

Reputation: 5670

Unable to set default value for Html.DropDownList in MVC 5

I am showing an enum as dropdown list in my Edit view like this:

Inside Model

public enum PaymentType
{
    Self=1,
    Insurer=2,
    PrivateCompany=3

}
public PaymentType PaymentTypeSelected { get; set; }

Inside Controller

ViewBag.EnumList = Patient.PaymentType.Insurer.ToSelectList();
patient.PaymentTypeSelected=Patient.PaymentType.Insurer;

In View

@Html.DropDownListFor(m => m.PaymentTypeSelected, 
    ViewBag.EnumList as SelectList)

And an Extension Function

public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj)
        where TEnum : struct, IComparable, IFormattable, IConvertible
{
    return new SelectList(Enum.GetValues(typeof(TEnum)).OfType<Enum>()
        .Select(x => new SelectListItem
        {
           Text = Enum.GetName(typeof(TEnum), x),
           Value = (Convert.ToInt32(x)).ToString()
        }), "Value", "Text");
    }

Generated HTML

<select data-val="true" 
        data-val-required="The PaymentTypeSelected field is required."
        id="ptype" name="PaymentTypeSelected">
    <option value="1">Self</option>
    <option value="2">Insurer</option>
    <option value="3">PrivateCompany</option>
</select>

It all looks okay to me, but the dropdown does not show default selected value (in my case Insurer). Can any one point out what I am doing wrong here?

Upvotes: 1

Views: 2384

Answers (4)

Sarmin Akter
Sarmin Akter

Reputation: 120

A SelectList can takes 4 arguments, where the last argument selectedValue is an object of whatever type is in your list. So you can try like the following:

ViewBag.yourEnumList= new SelectList(enumList, "Value", "Text", selectedValue);

Or, You can apply this in your extension function

Upvotes: 0

Shaun Luttin
Shaun Luttin

Reputation: 141462

Here it is as a working DotNetFiddle.

In short, you need to make sure that both the Value property of each SelectListItem and the PaymentTypeSelected property are pulling from the same Enum conversion. You were doing int for the Value and string for the PaymentTypeSelected. Change your extension to this and you're golden.

public static class MyExtensions
{
    public static SelectList ToSelectList<TEnum>(this TEnum obj) 
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var items = Enum.GetValues(typeof (TEnum))
                .OfType<Enum>()
                .Select(x => new { Text = x.ToString() })
                .Select(x => new SelectListItem
                {
                    Text = x.Text, 
                    Value = x.Text
                });

        return new SelectList(items, "Value", "Text");
    }
}

Upvotes: 3

Ray Suelzer
Ray Suelzer

Reputation: 4107

Try this...

 @Html.DropDownListFor(m => ((int)m.PaymentTypeSelected).ToString(), ViewBag.EnumList as SelectList)

Upvotes: 0

AaronLS
AaronLS

Reputation: 38367

As Stephen pointed out, this won't work if you use the DropDownListFor, as the model binding prefers the m=>m.SomeProperty over the constructor parameter.

You can use the SelectList constructor that takes a 4th object parameter to indicate the selected value: https://msdn.microsoft.com/en-us/library/dd492553(v=vs.118).aspx

// in controller we'll pass the desired selected value to extension method:
ViewBag.EnumList = Patient.PaymentType.Insurer.ToSelectList(Patient.PaymentType.Insurer);

// update method to support this parameter
public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj, object selectedValue)
        where TEnum : struct, IComparable, IFormattable, IConvertible // correct one
    {
        return new SelectList(
            Enum.GetValues(typeof(TEnum)).OfType<Enum>()
                 .Select(x =>
                     new SelectListItem
                     {
                         Text = Enum.GetName(typeof(TEnum), x),
                         Value = (Convert.ToInt32(x)).ToString()
                     }
                 ) 
            ,"Value", "Text"
            ,(int)selectedValue); // pass selected value to SelectList constructor

    }

I've made one edit to add (int), which is somewhat of a dirty cast since we're coming from an object. This of course can be improved upon.

Upvotes: 2

Related Questions