Html.EnumDropdownListFor: Showing a default text

C#asp.net MvcDrop Down-Menuasp.net Mvc-5.1

C# Problem Overview


In my view I have a enumdropdownlist (a new feature in Asp.Net MVC 5.1).

@Html.EnumDropDownListFor(m => m.SelectedLicense,new { @class="form-control"})

If I execute the above code I get dropdownlist for my following enum.

public enum LicenseTypes
{
    Trial = 0,
    Paid = 1
}

but by default I want my dropdownlist to have a value(custom text) and this is what I tried

@Html.EnumDropDownListFor(m => m.SelectedLicense,"Select a license" ,new { @class="form-control"})

but now the problem is when i run it, my dropdownlist looks like this enter image description here So, the default text I want to show doesn't appear by default. If a user selects "select a license" and tries to submit the form, it does show an error saying "select a license" but it doesn't show as default text. Something i need to change?

Ps: The image is the screenshot of the page when it loads. By default it'll show Trial as selected option.

C# Solutions


Solution 1 - C#

Try to change the Index of LicenseTypes start from 1 not 0 like below:

public enum LicenseTypes
{
    Trial = 1,
    Paid = 2
}

Then you can use Range attribute to validate the selected license type like below:

public class YourViewModel
{
     //Other properties
     [Range(1,int.MaxValue,ErrorMessage = "Select a correct license")]
     public LicenseTypes LicenseTypes { get; set; }
}

Finally, in your view:

   @Html.EnumDropDownListFor(m => m.LicenseTypes,"Select a license",new { @class = "form-control"})
   @Html.ValidationMessageFor(m => m.LicenseTypes)

Solution 2 - C#

By the time your EnumDropDownListFor is rendered SelectedLicense already has the default value for the type, which is 0.

Just change the type of your SelectedLicense property to a nullable enum, like so:

public LicenseTypes? SelectedLicense { get; set; }

This also allows you to continue using the Required attribute, which I think is significantly cleaner. The Required attribute will not allow a null response, so even though your model allows nulls, the form will not.

Solution 3 - C#

I have an enum:

public enum Sex
{
    Male,
    Female
}

In my model I have:

    [DisplayName("Sex")]
    [Required]
    public Sex? Sex { get; set; }

An in the view:

    @Html.EnumDropDownListFor(model => model.Sex, "Select sex", new { @class = "form-control", type = "text"})

By this I have a dropdown with default option "Select sex", but validation accepts only options provided by enum ("Male" and "Female").

In MVC3 (without EnumDropDownListFor) I used in model:

    [DisplayName("Sex")]
    [Required(AllowEmptyStrings=false)]
    public Sex? Sex { get; set; }

    Sex = null;

    Sexes = Repository.GetAutoSelectList<Sex>("");

In view:

    @Html.DropDownListFor(model => model.Sex, Model.Sexes, new { @class = "form-control", type = "text" })

Solution 4 - C#

The ViewModel class needs to have the default value set on the enum property for it to be the default selected public

public class Test
    {
        public Cars MyCars { get; set; }
        public enum Cars
        {
            [Display(Name = @"Car #1")]
            Car1 = 1,
            [Display(Name = @"Car #2")]
            Car2 = 2,
            [Display(Name = @"Car #3")]
            Car3 = 3
        }

    }

Controller:

 public class EnumController : Controller
    {
        // GET: Enum
        public ActionResult Index()
        {
            var model = new Test {MyCars = Test.Cars.Car3}; // set default value
            return View(model);
        }
        [HttpPost]
        public ActionResult Index(Test model)
        {
            .....
        }
    }

View:

@Html.BeginForm()
{
<div class="panel bg-white">
    <div class="panel-header fg-white">
        Enums
    </div>
    <div class="panel-content">
        <div class="input-control select size3">
            @Html.EnumDropDownListFor(model => model.MyCars)

        </div>
    </div>
    <input type="submit" class="button success large" />
</div>
}

Solution 5 - C#

Am I a bit late ?

Changing the values of the enum type is not very satisfying.

Neither is changing the model property to render it nullable and then add a [Required] attribute to prevent it to be nullable.

I propose to use the ViewBag to set the default selected value of the dropdown. The line 4 of the controller just bellow is the only important one.

EDIT : Ah... newbies... My first idea was to use ModelState.SetModelValue because my newbie instinct prevented me to simply try to set the desired value in the ViewBag since the dropdown was binded to the model. I was sure to have a problem: it would bind to the model's property, not to the ViewBag's property. I was all wrong: ViewBag is OK. I corrected the code.

Here is an example.

Model:

namespace WebApplication1.Models {

	public enum GoodMusic {
		Metal,
		HeavyMetal,
		PowerMetal,
		BlackMetal,
		ThashMetal,
		DeathMetal // . . .
	}

	public class Fan {
		[Required(ErrorMessage = "Don't be shy!")]
		public String Name { get; set; }
		[Required(ErrorMessage = "There's enough good music here for you to chose!")]
		public GoodMusic FavouriteMusic { get; set; }
	}
}

Controller:

namespace WebApplication1.Controllers {
	public class FanController : Controller {
		public ActionResult Index() {
			ViewBag.FavouriteMusic = string.Empty;
			//ModelState.SetModelValue( "FavouriteMusic", new ValueProviderResult( string.Empty, string.Empty, System.Globalization.CultureInfo.InvariantCulture ) );
			return View( "Index" );
		}
		[HttpPost, ActionName( "Index" )]
		public ActionResult Register( Models.Fan newFan ) {
			if( !ModelState.IsValid )
				return View( "Index" );
			ModelState.Clear();
			ViewBag.Message = "OK - You may register another fan";
			return Index();
		}
	}
}

View:

@model WebApplication1.Models.Fan
<h2>Hello, fan</h2>
@using( Html.BeginForm() ) {
	<p>@Html.LabelFor( m => m.Name )</p>
	<p>@Html.EditorFor( m => m.Name ) @Html.ValidationMessageFor( m => m.Name )</p>
	<p>@Html.LabelFor( m => m.FavouriteMusic )</p>
	<p>@Html.EnumDropDownListFor( m => m.FavouriteMusic, "Chose your favorite music from here..." ) @Html.ValidationMessageFor( m => m.FavouriteMusic )</p>
	<input type="submit" value="Register" />
	@ViewBag.Message
}

Without the "ModelState.SetModelValue or ViewBag.FavouriteMusic = string.Empty" line in the model Index action the default selected value would be "Metal" and not "Select your music..."

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCybercopView Question on Stackoverflow
Solution 1 - C#LinView Answer on Stackoverflow
Solution 2 - C#Michael RichardsonView Answer on Stackoverflow
Solution 3 - C#rsobonView Answer on Stackoverflow
Solution 4 - C#HaroonView Answer on Stackoverflow
Solution 5 - C#RikouView Answer on Stackoverflow