// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.TestCommon; using Microsoft.AspNet.Testing; using Microsoft.Framework.Internal; using Microsoft.Framework.WebEncoders; using Moq; using Xunit; namespace Microsoft.AspNet.Mvc.Rendering { public class HtmlHelperSelectTest { private static readonly SelectListGroup GroupOne = new SelectListGroup { Name = "Group One", }; private static readonly SelectListGroup GroupTwo = new SelectListGroup { Name = "Group Two", }; private static readonly SelectListGroup DisabledGroup = new SelectListGroup { Disabled = true, Name = "Disabled Group", }; private static readonly List BasicSelectList = new List { new SelectListItem { Text = "Zero", Value = "0"}, new SelectListItem { Text = "One", Value = "1"}, new SelectListItem { Text = "Two", Value = "2"}, new SelectListItem { Text = "Three", Value = "3"}, }; private static readonly List SomeDisabledOneSelectedSelectList = new List { new SelectListItem { Disabled = false, Selected = false, Text = "Zero", Value = "0"}, new SelectListItem { Disabled = true, Selected = true, Text = "One", Value = "1"}, new SelectListItem { Disabled = false, Selected = false, Text = "Two", Value = "2"}, new SelectListItem { Disabled = true, Selected = false, Text = "Three", Value = "3"}, }; private static readonly List SomeGroupedSomeSelectedSelectList = new List { new SelectListItem { Group = GroupOne, Selected = true, Text = "Zero", Value = "0"}, new SelectListItem { Group = GroupTwo, Selected = false, Text = "One", Value = "1"}, new SelectListItem { Group = GroupOne, Selected = true, Text = "Two", Value = "2"}, new SelectListItem { Group = null, Selected = false, Text = "Three", Value = "3"}, }; private static readonly List OneGroupSomeSelectedSelectList = new List { new SelectListItem { Group = GroupOne, Selected = true, Text = "Zero", Value = "0"}, new SelectListItem { Group = GroupOne, Selected = true, Text = "One", Value = "1"}, new SelectListItem { Group = GroupOne, Selected = false, Text = "Two", Value = "2"}, new SelectListItem { Group = GroupOne, Selected = false, Text = "Three", Value = "3"}, }; private static readonly List OneDisabledGroupAllSelectedSelectList = new List { new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Zero", Value = "0"}, new SelectListItem { Group = DisabledGroup, Selected = true, Text = "One", Value = "1"}, new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Two", Value = "2"}, new SelectListItem { Group = DisabledGroup, Selected = true, Text = "Three", Value = "3"}, }; private static readonly List SourcesSelectList = new List { new SelectListItem { Text = SelectSources.ModelStateEntry.ToString() }, new SelectListItem { Text = SelectSources.ModelStateEntryWithPrefix.ToString() }, new SelectListItem { Text = SelectSources.ViewDataEntry.ToString() }, new SelectListItem { Text = SelectSources.PropertyOfViewDataEntry.ToString() }, new SelectListItem { Text = SelectSources.ViewDataEntryWithPrefix.ToString() }, new SelectListItem { Text = SelectSources.PropertyOfViewDataEntryWithPrefix.ToString() }, new SelectListItem { Text = SelectSources.ModelValue.ToString() }, new SelectListItem { Text = SelectSources.PropertyOfModel.ToString() }, }; // Select list -> expected HTML with null model, expected HTML with model containing "2". public static TheoryData, string, string> DropDownListDataSet { get { return new TheoryData, string, string> { { BasicSelectList, "", "" }, { SomeDisabledOneSelectedSelectList, "", "" }, { SomeGroupedSomeSelectedSelectList, "", "" }, { OneGroupSomeSelectedSelectList, "", "" }, { OneDisabledGroupAllSelectedSelectList, "", "" }, }; } } // Select list -> expected HTML with null model, with model containing "2", and with model containing "1", "3". public static TheoryData, string, string, string> ListBoxDataSet { get { return new TheoryData, string, string, string> { { BasicSelectList, "", "", "" }, { SomeDisabledOneSelectedSelectList, "", "", "" }, { SomeGroupedSomeSelectedSelectList, "", "", "" }, { OneGroupSomeSelectedSelectList, "", "", "" }, { OneDisabledGroupAllSelectedSelectList, "", "", "" }, }; } } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownList_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(); var savedDisabled = selectList.Select(item => item.Disabled).ToList(); var savedGroup = selectList.Select(item => item.Group).ToList(); var savedSelected = selectList.Select(item => item.Selected).ToList(); var savedText = selectList.Select(item => item.Text).ToList(); var savedValue = selectList.Select(item => item.Value).ToList(); // Act var html = helper.DropDownList("Property1", selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); Assert.Equal(savedGroup, selectList.Select(item => item.Group)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedText, selectList.Select(item => item.Text)); Assert.Equal(savedValue, selectList.Select(item => item.Value)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownList_WithNullSelectList_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(); helper.ViewData["Property1"] = selectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownList("Property1", selectList: null, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownList_WithNullExpression_Throws( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var expected = "The name of an HTML field cannot be null or empty. Instead use methods " + "Microsoft.AspNet.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNet.Mvc.Rendering." + "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value." + Environment.NewLine + "Parameter name: expression"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(); // Act & Assert var ex = Assert.Throws( "expression", () => helper.DropDownList(null, selectList: null, optionLabel: null, htmlAttributes: null)); Assert.Equal(expected, ex.Message); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownList_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml, string expectedHtml) { // Arrange var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownList("Property1", selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void DropDownListNotInTemplate_GetsModelStateEntry() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: false); var modelState = new ModelStateDictionary { ["Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntry.ToString() }, AttemptedValue = SelectSources.ModelStateEntry.ToString() }, ["Prefix.Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() }, AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString() }, }; var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider, modelState) { ["Property1"] = SelectSources.ViewDataEntry, ["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix, ["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry }, }; viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListInTemplate_GetsModelStateEntry() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.ModelStateEntryWithPrefix, allowMultiple: false); var modelState = new ModelStateDictionary { ["Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntry.ToString() }, AttemptedValue = SelectSources.ModelStateEntry.ToString() }, ["Prefix.Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() }, AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString() }, }; var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider, modelState) { ["Property1"] = SelectSources.ViewDataEntry, ["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix, ["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry }, }; viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListNotInTemplate_GetsViewDataEntry_IfModelStateEmpty() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.ViewDataEntry, allowMultiple: false); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = SelectSources.ViewDataEntry, ["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix, ["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry }, }; viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListInTemplate_GetsViewDataEntry_IfModelStateEmpty() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.ViewDataEntryWithPrefix, allowMultiple: false); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = SelectSources.ViewDataEntry, ["Prefix.Property1"] = SelectSources.ViewDataEntryWithPrefix, ["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry }, }; viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListInTemplate_GetsPropertyOfViewDataEntry_IfModelStateEmptyAndNoViewDataEntryWithPrefix() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.PropertyOfViewDataEntry, allowMultiple: false); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = SelectSources.ViewDataEntry, ["Prefix"] = new ModelContainingSources { Property1 = SelectSources.PropertyOfViewDataEntry }, }; viewData.Model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListNotInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.PropertyOfModel, allowMultiple: false); var model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void DropDownListInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix(SelectSources.PropertyOfModel, allowMultiple: false); var model = new ModelContainingSources { Property1 = SelectSources.PropertyOfModel }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewContext.ClientValidationEnabled = false; helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; // Act var html = helper.DropDownList("Property1", SourcesSelectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListFor_WithNullModel_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor( value => value.Property1, selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListFor_WithNullModelAndNullSelectList_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(); helper.ViewData["Property1"] = selectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor( value => value.Property1, selectList: null, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListFor_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml, string expectedHtml) { // Arrange var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor( value => value.Property1, selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListFor_WithModelValueAndNullSelectList_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml, string expectedHtml) { // Arrange var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewData["Property1"] = selectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor( value => value.Property1, selectList: null, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void DropDownListFor_WithIndexerExpression_GeneratesExpectedValue() { // Arrange var model = new ModelContainingList { Property1 = { "0", "1", "2" } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var selectList = SomeDisabledOneSelectedSelectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); var expectedHtml = ""; // Act var html = helper.DropDownListFor( value => value.Property1[2], selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void DropDownListFor_WithUnrelatedExpression_GeneratesExpectedValue() { // Arrange var unrelated = "2"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(); var selectList = SomeDisabledOneSelectedSelectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); var expectedHtml = ""; // Act var html = helper.DropDownListFor(value => unrelated, selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBox_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( IEnumerable selectList, string expectedHtml, string ignoredHtml1, string ignoredHtml2) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); var savedDisabled = selectList.Select(item => item.Disabled).ToList(); var savedGroup = selectList.Select(item => item.Group).ToList(); var savedSelected = selectList.Select(item => item.Selected).ToList(); var savedText = selectList.Select(item => item.Text).ToList(); var savedValue = selectList.Select(item => item.Value).ToList(); // Act var html = helper.ListBox("Property1", selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); Assert.Equal(savedGroup, selectList.Select(item => item.Group)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedText, selectList.Select(item => item.Text)); Assert.Equal(savedValue, selectList.Select(item => item.Value)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBox_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string expectedHtml, string ignoredHtml2) { // Arrange var model = new ModelContainingList { Property1 = { "2" } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBox("Property1", selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBox_WithMultipleModelValues_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string ignoredHtml2, string expectedHtml) { // Arrange var model = new ModelContainingList { Property1 = { "1", "3" } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBox("Property1", selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void ListBoxNotInTemplate_GetsModelStateEntry() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: true); var modelState = new ModelStateDictionary { ["Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntry.ToString() }, AttemptedValue = SelectSources.ModelStateEntry.ToString() }, ["Prefix.Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() }, AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString() }, }; var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider, modelState) { ["Property1"] = new[] { SelectSources.ViewDataEntry }, ["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix }, ["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } }, }; viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxInTemplate_GetsModelStateEntry() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.ModelStateEntryWithPrefix, allowMultiple: true); var modelState = new ModelStateDictionary { ["Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntry.ToString() }, AttemptedValue = SelectSources.ModelStateEntry.ToString() }, ["Prefix.Property1"] = new ModelState { RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() }, AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString() }, }; var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider, modelState) { ["Property1"] = new[] { SelectSources.ViewDataEntry }, ["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix }, ["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } }, }; viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxNotInTemplate_GetsViewDataEntry_IfModelStateEmpty() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.ViewDataEntry, allowMultiple: true); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = new[] { SelectSources.ViewDataEntry }, ["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix }, ["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } }, }; viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxInTemplate_GetsViewDataEntry_IfModelStateEmpty() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.ViewDataEntryWithPrefix, allowMultiple: true); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = new[] { SelectSources.ViewDataEntry }, ["Prefix.Property1"] = new[] { SelectSources.ViewDataEntryWithPrefix }, ["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } }, }; viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxInTemplate_GetsPropertyOfViewDataEntry_IfModelStateEmptyAndNoViewDataEntryWithPrefix() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix( SelectSources.PropertyOfViewDataEntry, allowMultiple: true); var provider = TestModelMetadataProvider.CreateDefaultProvider(); var viewData = new ViewDataDictionary(provider) { ["Property1"] = new[] { SelectSources.ViewDataEntry }, ["Prefix"] = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfViewDataEntry } }, }; viewData.Model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; viewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxNotInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty() { // Arrange var expectedHtml = GetExpectedSelectElement(SelectSources.PropertyOfModel, allowMultiple: true); var model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewContext.ClientValidationEnabled = false; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Fact] public void ListBoxInTemplate_GetsPropertyOfModel_IfModelStateAndViewDataEmpty() { // Arrange var expectedHtml = GetExpectedSelectElementWithPrefix(SelectSources.PropertyOfModel, allowMultiple: true); var model = new ModelContainingListOfSources { Property1 = { SelectSources.PropertyOfModel } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewContext.ClientValidationEnabled = false; helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; // Act var html = helper.ListBox("Property1", SourcesSelectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxFor_WithNullModel_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml1, string ignoredHtml2) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxFor_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string expectedHtml, string ignoredHtml2) { // Arrange var model = new ModelContainingList { Property1 = { "2" } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void ListBoxFor_WithUnreleatedExpression_GeneratesExpectedValue() { // Arrange var unrelated = new[] { "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(); var selectList = SomeDisabledOneSelectedSelectList; var savedSelected = selectList.Select(item => item.Selected).ToList(); var expectedHtml = ""; // Act var html = helper.ListBoxFor(value => unrelated, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxFor_WithMultipleModelValues_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string ignoredHtml2, string expectedHtml) { // Arrange var model = new ModelContainingList { Property1 = { "1", "3" } }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListInTemplate_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedDisabled = selectList.Select(item => item.Disabled).ToList(); var savedGroup = selectList.Select(item => item.Group).ToList(); var savedSelected = selectList.Select(item => item.Selected).ToList(); var savedText = selectList.Select(item => item.Text).ToList(); var savedValue = selectList.Select(item => item.Value).ToList(); // Act var html = helper.DropDownList( expression: string.Empty, selectList: selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); Assert.Equal(savedGroup, selectList.Select(item => item.Group)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedText, selectList.Select(item => item.Text)); Assert.Equal(savedValue, selectList.Select(item => item.Value)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListInTemplate_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml, string expectedHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper("2"); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownList( expression: string.Empty, selectList: selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListForInTemplate_WithNullModel_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor(value => value, selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(DropDownListDataSet))] public void DropDownListForInTemplate_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml, string expectedHtml) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper("2"); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.DropDownListFor(value => value, selectList, optionLabel: null, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxInTemplate_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( IEnumerable selectList, string expectedHtml, string ignoredHtml1, string ignoredHtml2) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper>(model: null); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedDisabled = selectList.Select(item => item.Disabled).ToList(); var savedGroup = selectList.Select(item => item.Group).ToList(); var savedSelected = selectList.Select(item => item.Selected).ToList(); var savedText = selectList.Select(item => item.Text).ToList(); var savedValue = selectList.Select(item => item.Value).ToList(); // Act var html = helper.ListBox(expression: string.Empty, selectList: selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); Assert.Equal(savedGroup, selectList.Select(item => item.Group)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); Assert.Equal(savedText, selectList.Select(item => item.Text)); Assert.Equal(savedValue, selectList.Select(item => item.Value)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxInTemplate_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string expectedHtml, string ignoredHtml2) { // Arrange var model = new List { "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBox(expression: string.Empty, selectList: selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxForInTemplate_WithNullModel_GeneratesExpectedValue( IEnumerable selectList, string expectedHtml, string ignoredHtml1, string ignoredHtml2) { // Arrange var helper = DefaultTemplatesUtilities.GetHtmlHelper>(model: null); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBoxFor(value => value, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Theory] [MemberData(nameof(ListBoxDataSet))] public void ListBoxForInTemplate_WithModelValue_GeneratesExpectedValue( IEnumerable selectList, string ignoredHtml1, string expectedHtml, string ignoredHtml2) { // Arrange var model = new List { "2" }; var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); helper.ViewData.TemplateInfo.HtmlFieldPrefix = "Property1"; var savedSelected = selectList.Select(item => item.Selected).ToList(); // Act var html = helper.ListBoxFor(value => value, selectList, htmlAttributes: null); // Assert Assert.Equal(expectedHtml, HtmlContentUtilities.HtmlContentToString(html)); Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); } [Fact] public void GetEnumSelectListTEnum_ThrowsWithFlagsEnum() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act & Assert ExceptionAssert.ThrowsArgument( () => htmlHelper.GetEnumSelectList(), "TEnum", $"The type '{ typeof(EnumWithFlags).FullName }' is not supported."); } [Fact] public void GetEnumSelectListTEnum_ThrowsWithNonEnum() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act & Assert ExceptionAssert.ThrowsArgument( () => htmlHelper.GetEnumSelectList(), "TEnum", $"The type '{ typeof(StructWithFields).FullName }' is not supported."); } [Fact] public void GetEnumSelectListTEnum_WrapsGetEnumSelectListModelMetadata() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var metadata = metadataProvider.GetMetadataForType(typeof(EnumWithFields)); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act var result = htmlHelper.GetEnumSelectList(); // Assert Assert.Equal(metadata.ModelType, htmlHelper.Metadata.ModelType); Assert.Same(htmlHelper.SelectListItems, result); // No replacement of the underlying List VerifySelectList(htmlHelper.CopiedSelectListItems, result); // No change to the (mutable) items } [Fact] public void GetEnumSelectListType_ThrowsWithFlagsEnum() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act & Assert ExceptionAssert.ThrowsArgument( () => htmlHelper.GetEnumSelectList(typeof(EnumWithFlags)), "enumType", $"The type '{ typeof(EnumWithFlags).FullName }' is not supported."); } [Fact] public void GetEnumSelectListType_ThrowsWithNonEnum() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act & Assert ExceptionAssert.ThrowsArgument( () => htmlHelper.GetEnumSelectList(typeof(StructWithFields)), "enumType", $"The type '{ typeof(StructWithFields).FullName }' is not supported."); } [Fact] public void GetEnumSelectListType_ThrowsWithNonStruct() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act & Assert ExceptionAssert.ThrowsArgument( () => htmlHelper.GetEnumSelectList(typeof(ClassWithFields)), "enumType", $"The type '{ typeof(ClassWithFields).FullName }' is not supported."); } [Fact] public void GetEnumSelectListType_WrapsGetEnumSelectListModelMetadata() { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var metadata = metadataProvider.GetMetadataForType(typeof(EnumWithFields)); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act var result = htmlHelper.GetEnumSelectList(typeof(EnumWithFields)); // Assert Assert.Equal(metadata.ModelType, htmlHelper.Metadata.ModelType); Assert.Same(htmlHelper.SelectListItems, result); // No replacement of the underlying List VerifySelectList(htmlHelper.CopiedSelectListItems, result); // No change to the (mutable) items } public static TheoryData> GetEnumSelectListData { get { return new TheoryData> { { typeof(EmptyEnum), Enumerable.Empty() }, { typeof(EmptyEnum?), Enumerable.Empty() }, { typeof(EnumWithDisplayNames), new List { new SelectListItem { Text = "cero", Value = "0" }, new SelectListItem { Text = nameof(EnumWithDisplayNames.One), Value = "1" }, new SelectListItem { Text = "dos", Value = "2" }, new SelectListItem { Text = "tres", Value = "3" }, new SelectListItem { Text = "name from resources", Value = "-2" }, new SelectListItem { Text = "menos uno", Value = "-1" }, } }, { typeof(EnumWithDisplayNames?), new List { new SelectListItem { Text = "cero", Value = "0" }, new SelectListItem { Text = nameof(EnumWithDisplayNames.One), Value = "1" }, new SelectListItem { Text = "dos", Value = "2" }, new SelectListItem { Text = "tres", Value = "3" }, new SelectListItem { Text = "name from resources", Value = "-2" }, new SelectListItem { Text = "menos uno", Value = "-1" }, } }, { typeof(EnumWithDuplicates), new List { new SelectListItem { Text = nameof(EnumWithDuplicates.Zero), Value = "0" }, new SelectListItem { Text = nameof(EnumWithDuplicates.None), Value = "0" }, new SelectListItem { Text = nameof(EnumWithDuplicates.One), Value = "1" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Duece), Value = "2" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Two), Value = "2" }, new SelectListItem { Text = nameof(EnumWithDuplicates.MoreThanTwo), Value = "3" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Three), Value = "3" }, } }, { typeof(EnumWithDuplicates?), new List { new SelectListItem { Text = nameof(EnumWithDuplicates.Zero), Value = "0" }, new SelectListItem { Text = nameof(EnumWithDuplicates.None), Value = "0" }, new SelectListItem { Text = nameof(EnumWithDuplicates.One), Value = "1" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Duece), Value = "2" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Two), Value = "2" }, new SelectListItem { Text = nameof(EnumWithDuplicates.MoreThanTwo), Value = "3" }, new SelectListItem { Text = nameof(EnumWithDuplicates.Three), Value = "3" }, } }, { typeof(EnumWithFields), new List { new SelectListItem { Text = nameof(EnumWithFields.Zero), Value = "0" }, new SelectListItem { Text = nameof(EnumWithFields.One), Value = "1" }, new SelectListItem { Text = nameof(EnumWithFields.Two), Value = "2" }, new SelectListItem { Text = nameof(EnumWithFields.Three), Value = "3" }, new SelectListItem { Text = nameof(EnumWithFields.MinusTwo), Value = "-2" }, new SelectListItem { Text = nameof(EnumWithFields.MinusOne), Value = "-1" }, } }, { typeof(EnumWithFields?), new List { new SelectListItem { Text = nameof(EnumWithFields.Zero), Value = "0" }, new SelectListItem { Text = nameof(EnumWithFields.One), Value = "1" }, new SelectListItem { Text = nameof(EnumWithFields.Two), Value = "2" }, new SelectListItem { Text = nameof(EnumWithFields.Three), Value = "3" }, new SelectListItem { Text = nameof(EnumWithFields.MinusTwo), Value = "-2" }, new SelectListItem { Text = nameof(EnumWithFields.MinusOne), Value = "-1" }, } }, }; } } [Theory] [MemberData(nameof(GetEnumSelectListData))] public void GetEnumSelectList_ReturnsExpectedItems(Type type, IEnumerable expected) { // Arrange var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var metadata = metadataProvider.GetMetadataForType(type); var htmlHelper = new TestHtmlHelper(metadataProvider); // Act var result = htmlHelper.GetEnumSelectList(type); // Assert // OrderBy is used because the order of the results may very depending on the platform / client. VerifySelectList( expected.OrderBy(item => item.Text, StringComparer.Ordinal), result.OrderBy(item => item.Text, StringComparer.Ordinal)); } private static string GetExpectedSelectElement(SelectSources source, bool allowMultiple) { return $""; } private static string GetExpectedSelectElementWithPrefix(SelectSources source, bool allowMultiple) { return $""; } private static string GetMultiple(bool allowMultiple) { return allowMultiple ? " multiple=\"HtmlEncode[[multiple]]\"" : string.Empty; } private static string GetOption(SelectSources optionSource, SelectSources source) { return $"HtmlEncode[[{ optionSource.ToString() }]]"; } private static string GetSelected(SelectSources optionSource, SelectSources source) { return optionSource == source ? " selected=\"HtmlEncode[[selected]]\"" : string.Empty; } // Confirm methods that wrap GetEnumSelectList(ModelMetadata) are not changing anything in returned collection. private void VerifySelectList(IEnumerable expected, IEnumerable actual) { Assert.NotNull(actual); Assert.Equal(expected.Count(), actual.Count()); for (var i = 0; i < actual.Count(); i++) { var expectedItem = expected.ElementAt(i); var actualItem = actual.ElementAt(i); Assert.False(actualItem.Disabled); Assert.Null(actualItem.Group); Assert.False(actualItem.Selected); Assert.Equal(expectedItem.Text, actualItem.Text); Assert.Equal(expectedItem.Value, actualItem.Value); } } private class TestHtmlHelper : HtmlHelper { public TestHtmlHelper([NotNull] IModelMetadataProvider metadataProvider) : base( new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object, metadataProvider, new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object, new Mock(MockBehavior.Strict).Object) { } public ModelMetadata Metadata { get; private set; } public IEnumerable SelectListItems { get; private set; } public IEnumerable CopiedSelectListItems { get; private set; } protected override IEnumerable GetEnumSelectList([NotNull] ModelMetadata metadata) { Metadata = metadata; SelectListItems = base.GetEnumSelectList(metadata); if (SelectListItems != null) { // Perform a deep copy to help confirm the mutable items are not changed. var copiedSelectListItems = new List(); CopiedSelectListItems = copiedSelectListItems; foreach (var item in SelectListItems) { var copy = new SelectListItem { Disabled = item.Disabled, Group = item.Group, Selected = item.Selected, Text = item.Text, Value = item.Value, }; copiedSelectListItems.Add(copy); } } return SelectListItems; } } private enum SelectSources { ModelStateEntry, ModelStateEntryWithPrefix, ViewDataEntry, PropertyOfViewDataEntry, ViewDataEntryWithPrefix, PropertyOfViewDataEntryWithPrefix, ModelValue, PropertyOfModel, }; private class ModelContainingSources { public SelectSources Property1 { get; set; } } private class ModelContainingListOfSources { public List Property1 { get; } = new List(); } private class ClassWithFields { public const int Zero = 0; public const int One = 1; } private enum EmptyEnum { } private enum EnumWithDisplayNames { [Display(Name = "tres")] Three = 3, [Display(Name = "dos")] Two = 2, // Display attribute exists but does not set Name. [Display(ShortName = "uno")] One = 1, [Display(Name = "cero")] Zero = 0, [Display(Name = "menos uno")] MinusOne = -1, #if USE_REAL_RESOURCES [Display(Name = nameof(Test.Resources.DisplayAttribute_Name), ResourceType = typeof(Test.Resources))] #else [Display(Name = nameof(TestResources.DisplayAttribute_Name), ResourceType = typeof(TestResources))] #endif MinusTwo = -2, } private enum EnumWithDuplicates { Zero = 0, One = 1, Three = 3, MoreThanTwo = 3, Two = 2, None = 0, Duece = 2, } [Flags] private enum EnumWithFlags { Four = 4, Two = 2, One = 1, Zero = 0, All = -1, } private enum EnumWithFields { MinusTwo = -2, MinusOne = -1, Three = 3, Two = 2, One = 1, Zero = 0, } private struct StructWithFields { public const int Zero = 0; public const int One = 1; } private class ModelContainingList { public List Property1 { get; } = new List(); } } }