// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web.Mvc.Test;
using Microsoft.TestCommon;
using Microsoft.Web.UnitTestUtil;

namespace System.Web.Mvc.Html.Test
{
    public class SelectExtensionsTest
    {
        private static readonly ViewDataDictionary<FooModel> _listBoxViewData = new ViewDataDictionary<FooModel> { { "foo", new[] { "Bravo" } } };
        private static readonly ViewDataDictionary<FooModel> _dropDownListViewData = new ViewDataDictionary<FooModel> { { "foo", "Bravo" } };
        private static readonly ViewDataDictionary<NonIEnumerableModel> _nonIEnumerableViewData = new ViewDataDictionary<NonIEnumerableModel> { { "foo", 1 } };

        private static ViewDataDictionary GetViewDataWithSelectList()
        {
            ViewDataDictionary viewData = new ViewDataDictionary();
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");
            viewData["foo"] = selectList;
            viewData["foo.bar"] = selectList;
            return viewData;
        }

        // DropDownList

        [Fact]
        public void DropDownListUsesExplicitValueIfNotProvidedInViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesExplicitValueIfNotProvidedInViewData_Unobtrusive()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ClientValidationRuleFactory = (name, metadata) => new[] { new ModelClientValidationRule { ValidationType = "type", ErrorMessage = "error" } };
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select data-val=\"true\" data-val-type=\"error\" id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesViewDataDefaultValue()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(_dropDownListViewData);
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), "Charlie");

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesViewDataDefaultValueNoOptionLabel()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(_dropDownListViewData);
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), "Charlie");

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithAttributesDictionary()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, HtmlHelperTest.AttributesDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithEmptyNameThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());

            // Act & Assert
            Assert.ThrowsArgumentNullOrEmpty(
                delegate { helper.DropDownList(String.Empty, (SelectList)null /* selectList */, (string)null /* optionLabel */); },
                "name");
        }

        [Fact]
        public void DropDownListWithErrors()
        {
            // Arrange
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });
            ViewDataDictionary viewData = GetViewDataWithErrors();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" class=\"input-validation-error\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithErrorsAndCustomClass()
        {
            // Arrange
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            ViewDataDictionary viewData = GetViewDataWithErrors();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, new { @class = "foo-class" });

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error foo-class\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithNullNameThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());

            // Act & Assert
            Assert.ThrowsArgumentNullOrEmpty(
                delegate { helper.DropDownList(null /* name */, (SelectList)null /* selectList */, (string)null /* optionLabel */); },
                "name");
        }

        [Fact]
        public void DropDownListWithNullSelectListUsesViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            helper.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionary()
        {
            // Arrange
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            ViewDataDictionary viewData = new ViewDataDictionary();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryWithUnderscores()
        {
            // Arrange
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            ViewDataDictionary viewData = new ViewDataDictionary();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryAndSelectList()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryAndSelectListNoOptionLabel()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryWithUnderscoresAndSelectListNoOptionLabel()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryAndEmptyOptionLabel()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, String.Empty /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option value=\"\"></option>" + Environment.NewLine
              + "<option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithObjectDictionaryAndTitle()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, "[Select Something]", HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option value=\"\">[Select Something]</option>" + Environment.NewLine
              + "<option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesViewDataSelectList()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(GetViewDataWithSelectList());

            // Act
            MvcHtmlString html = helper.DropDownList("foo", (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesModelState()
        {
            // Arrange
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            ViewDataDictionary viewData = GetViewDataWithErrors();
            viewData["foo"] = selectList;
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListUsesViewDataSelectListNoOptionLabel()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(GetViewDataWithSelectList());

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithDotReplacementForId()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(GetViewDataWithSelectList());

            // Act
            MvcHtmlString html = helper.DropDownList("foo.bar");

            // Assert
            Assert.Equal(
                "<select id=\"foo_bar\" name=\"foo.bar\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithIEnumerableSelectListItem()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", MultiSelectListTest.GetSampleIEnumerableObjects() } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithIEnumerableSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", "123456789" } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", MultiSelectListTest.GetSampleIEnumerableObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithListOfSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", "123456789" } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownList("foo", MultiSelectListTest.GetSampleListObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithListOfSelectListItem()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", MultiSelectListTest.GetSampleListObjects() } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithNullViewDataValueThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());

            // Act
            Assert.Throws<InvalidOperationException>(
                delegate { helper.DropDownList("foo", (string)null /* optionLabel */); },
                "There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'foo'.");
        }

        [Fact]
        public void DropDownListWithWrongViewDataTypeValueThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary { { "foo", 123 } });

            // Act
            Assert.Throws<InvalidOperationException>(
                delegate { helper.DropDownList("foo", (string)null /* optionLabel */); },
                "The ViewData item that has the key 'foo' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.");
        }

        [Fact]
        public void DropDownListWithPrefix()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.DropDownList("foo", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix_foo\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithPrefixAndEmptyName()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.DropDownList("", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix\" name=\"MyPrefix\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListWithPrefixAndNullSelectListUsesViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            helper.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.DropDownList("foo");

            // Assert
            Assert.Equal(
                "<select id=\"MyPrefix_foo\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        // DropDownListFor

        [Fact]
        public void DropDownListForWithNullExpressionThrows()
        {
            // Arrange
            HtmlHelper<object> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<object>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act & Assert
            Assert.ThrowsArgumentNull(
                () => helper.DropDownListFor<object, object>(null /* expression */, selectList),
                "expression"
                );
        }

        [Fact]
        public void DropDownListForUsesExplicitValueIfNotProvidedInViewData()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForUsesExplicitValueIfNotProvidedInViewData_Unobtrusive()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ClientValidationRuleFactory = (name, metadata) => new[] { new ModelClientValidationRule { ValidationType = "type", ErrorMessage = "error" } };
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select data-val=\"true\" data-val-type=\"error\" id=\"foo\" name=\"foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithEnumerableModel_Unobtrusive()
        {
            // Arrange
            HtmlHelper<IEnumerable<RequiredModel>> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<IEnumerable<RequiredModel>>());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            using (HtmlHelperTest.ReplaceCulture("en-US", "en-US"))
            {
                // Act
                MvcHtmlString html = helper.DropDownListFor(m => m.ElementAt(0).foo, selectList);

                // Assert
                Assert.Equal(
                    "<select data-val=\"true\" data-val-required=\"The foo field is required.\" id=\"MyPrefix_foo\" name=\"MyPrefix.foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
                  + "<option value=\"B\">Bravo</option>" + Environment.NewLine
                  + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
                  + "</select>",
                    html.ToHtmlString());
            }
        }

        [Fact]
        public void DropDownListForUsesViewDataDefaultValue()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(_dropDownListViewData);
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), "Charlie");

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, (string)null /* optionLabel */);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForUsesViewDataDefaultValueNoOptionLabel()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(_dropDownListViewData);
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), "Charlie");

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithAttributesDictionary()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, null /* optionLabel */, HtmlHelperTest.AttributesDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithErrors()
        {
            // Arrange
            HtmlHelper<FooBarModel> helper = MvcHelper.GetHtmlHelper(GetViewDataWithErrors());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" class=\"input-validation-error\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithErrorsAndCustomClass()
        {
            // Arrange
            HtmlHelper<FooBarModel> helper = MvcHelper.GetHtmlHelper(GetViewDataWithErrors());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, null /* optionLabel */, new { @class = "foo-class" });

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error foo-class\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionary()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionaryWithUnderscores()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, null /* optionLabel */, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionaryAndSelectListNoOptionLabel()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionaryWithUnderscoresAndSelectListNoOptionLabel()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionaryAndEmptyOptionLabel()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, String.Empty /* optionLabel */, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option value=\"\"></option>" + Environment.NewLine
              + "<option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithObjectDictionaryAndTitle()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, "[Select Something]", HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" name=\"foo\"><option value=\"\">[Select Something]</option>" + Environment.NewLine
              + "<option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithIEnumerableSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", "123456789" } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, MultiSelectListTest.GetSampleIEnumerableObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithListOfSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", "123456789" } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, MultiSelectListTest.GetSampleListObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithPrefix()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix_foo\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithPrefixAndEmptyName()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            SelectList selectList = new SelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m, selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix\" name=\"MyPrefix\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void DropDownListForWithPrefixAndIEnumerableSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", "123456789" } };
            vdd.TemplateInfo.HtmlFieldPrefix = "MyPrefix";
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.DropDownListFor(m => m.foo, MultiSelectListTest.GetSampleIEnumerableObjects());

            // Assert
            Assert.Equal(
                "<select id=\"MyPrefix_foo\" name=\"MyPrefix.foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        // ListBox

        [Fact]
        public void ListBoxUsesExplicitValueIfNotProvidedInViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", new[] { "A", "C" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxUsesExplicitValueIfNotProvidedInViewData_Unobtrusive()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ClientValidationRuleFactory = (name, metadata) => new[] { new ModelClientValidationRule { ValidationType = "type", ErrorMessage = "error" } };
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", new[] { "A", "C" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList);

            // Assert
            Assert.Equal(
                "<select data-val=\"true\" data-val-type=\"error\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxUsesViewDataDefaultValue()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(_listBoxViewData);
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithErrors()
        {
            // Arrange
            ViewDataDictionary viewData = GetViewDataWithErrors();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);
            MultiSelectList list = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", list);

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithErrorsAndCustomClass()
        {
            // Arrange
            ViewDataDictionary viewData = GetViewDataWithErrors();
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, new { @class = "foo-class" });

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error foo-class\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithNameOnly()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            helper.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBox("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithAttributesDictionary()
        {
            // Arrange
            ViewDataDictionary viewData = new ViewDataDictionary();
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            //viewData["foo"] = selectList;
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, HtmlHelperTest.AttributesDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithAttributesDictionaryAndMultiSelectList()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, HtmlHelperTest.AttributesDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithAttributesDictionaryOverridesName()
        {
            // DevDiv Bugs #217602:
            // SelectInternal() should override the user-provided 'name' attribute

            // Arrange
            ViewDataDictionary viewData = new ViewDataDictionary();
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            HtmlHelper helper = MvcHelper.GetHtmlHelper(viewData);

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, new { myAttr = "myValue", name = "theName" });

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" myAttr=\"myValue\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithEmptyNameThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());

            // Act & Assert
            Assert.ThrowsArgumentNullOrEmpty(
                delegate { helper.ListBox(String.Empty, (MultiSelectList)null /* selectList */); },
                "name");
        }

        [Fact]
        public void ListBoxWithNullNameThrows()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());

            // Act & Assert
            Assert.ThrowsArgumentNullOrEmpty(
                delegate { helper.ListBox(null /* name */, (MultiSelectList)null /* selectList */); },
                "name");
        }

        [Fact]
        public void ListBoxWithNullSelectListUsesViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            helper.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBox("foo", null);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithObjectDictionary()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithObjectDictionaryWithUnderscores()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithIEnumerableSelectListItem()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", MultiSelectListTest.GetSampleIEnumerableObjects() } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBox("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxThrowsWhenExpressionDoesNotEvaluateToIEnumerable()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", 123456789 } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => helper.ListBox("foo", MultiSelectListTest.GetSampleIEnumerableObjects()),
                "The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed."
                );
        }

        [Fact]
        public void ListBoxThrowsWhenExpressionEvaluatesToString()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", "123456789" } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => helper.ListBox("foo", MultiSelectListTest.GetSampleIEnumerableObjects()),
                "The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed."
                );
        }

        [Fact]
        public void ListBoxWithListOfSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", new string[] { "123456789", "111111111" } } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBox("foo", MultiSelectListTest.GetSampleListObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithListOfSelectListItem()
        {
            // Arrange
            ViewDataDictionary vdd = new ViewDataDictionary { { "foo", MultiSelectListTest.GetSampleListObjects() } };
            HtmlHelper helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBox("foo");

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithPrefix()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.ListBox("foo", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix_foo\" multiple=\"multiple\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithPrefixAndEmptyName()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.ListBox("", selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix\" multiple=\"multiple\" name=\"MyPrefix\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxWithPrefixAndNullSelectListUsesViewData()
        {
            // Arrange
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            helper.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.ListBox("foo");

            // Assert
            Assert.Equal(
                "<select id=\"MyPrefix_foo\" multiple=\"multiple\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        // ListBoxFor

        [Fact]
        public void ListBoxForWithNullExpressionThrows()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());

            // Act & Assert
            Assert.ThrowsArgumentNull(
                () => helper.ListBoxFor<FooModel, object>(null, null),
                "expression");
        }

        [Fact]
        public void ListBoxForUsesExplicitValueIfNotProvidedInViewData()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", new[] { "A", "C" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForUsesExplicitValueIfNotProvidedInViewData_Unobtrusive()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ClientValidationRuleFactory = (name, metadata) => new[] { new ModelClientValidationRule { ValidationType = "type", ErrorMessage = "error" } };
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", new[] { "A", "C" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList);

            // Assert
            Assert.Equal(
                "<select data-val=\"true\" data-val-type=\"error\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithEnumerableModel_Unobtrusive()
        {
            // Arrange
            HtmlHelper<IEnumerable<RequiredModel>> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<IEnumerable<RequiredModel>>());
            helper.ViewContext.ClientValidationEnabled = true;
            helper.ViewContext.UnobtrusiveJavaScriptEnabled = true;
            helper.ViewContext.FormContext = new FormContext();
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleAnonymousObjects(), "Letter", "FullWord", "C");

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.ElementAt(0).foo, selectList);

            // Assert
            Assert.Equal(
                "<select data-val=\"true\" data-val-required=\"The foo field is required.\" id=\"MyPrefix_foo\" multiple=\"multiple\" name=\"MyPrefix.foo\"><option value=\"A\">Alpha</option>" + Environment.NewLine
              + "<option value=\"B\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"C\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForUsesViewDataDefaultValue()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(_listBoxViewData);
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithErrors()
        {
            // Arrange
            HtmlHelper<FooBarModel> helper = MvcHelper.GetHtmlHelper(GetViewDataWithErrors());
            MultiSelectList list = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, list);

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithErrorsAndCustomClass()
        {
            // Arrange
            HtmlHelper<FooBarModel> helper = MvcHelper.GetHtmlHelper(GetViewDataWithErrors());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, new { @class = "foo-class" });

            // Assert
            Assert.Equal(
                "<select class=\"input-validation-error foo-class\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option selected=\"selected\">Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithAttributesDictionary()
        {
            // Arrange
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, HtmlHelperTest.AttributesDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithAttributesDictionaryOverridesName()
        {
            // DevDiv Bugs #217602:
            // SelectInternal() should override the user-provided 'name' attribute

            // Arrange
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, new { myAttr = "myValue", name = "theName" });

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" myAttr=\"myValue\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithNullSelectListUsesViewData()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            helper.ViewContext.ViewData["foo"] = new MultiSelectList(MultiSelectListTest.GetSampleStrings(), new[] { "Charlie" });

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, null);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option selected=\"selected\">Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithObjectDictionary()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithObjectDictionaryWithUnderscores()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectUnderscoresDictionary);

            // Assert
            Assert.Equal(
                "<select foo-baz=\"BazObjValue\" id=\"foo\" multiple=\"multiple\" name=\"foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithIEnumerableSelectListItem()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", MultiSelectListTest.GetSampleIEnumerableObjects() } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, null);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForThrowsWhenExpressionDoesNotEvaluateToIEnumerable()
        {
            // Arrange
            ViewDataDictionary<NonIEnumerableModel> vdd = new ViewDataDictionary<NonIEnumerableModel> { { "foo", 123456789 } };
            HtmlHelper<NonIEnumerableModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => helper.ListBoxFor(m => m.foo, MultiSelectListTest.GetSampleIEnumerableObjects()),
                "The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed."
                );
        }

        [Fact]
        public void ListBoxForThrowsWhenExpressionEvaluatesToString()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", "123456789" } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => helper.ListBoxFor(m => m.foo, MultiSelectListTest.GetSampleIEnumerableObjects()),
                "The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed."
                );
        }

        [Fact]
        public void ListBoxForWithListOfSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", new string[] { "123456789", "111111111" } } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, MultiSelectListTest.GetSampleListObjects());

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithListOfSelectListItem()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", MultiSelectListTest.GetSampleListObjects() } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, null);

            // Assert
            Assert.Equal(
                "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithPrefix()
        {
            // Arrange
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(new ViewDataDictionary<FooModel>());
            MultiSelectList selectList = new MultiSelectList(MultiSelectListTest.GetSampleStrings());
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, selectList, HtmlHelperTest.AttributesObjectDictionary);

            // Assert
            Assert.Equal(
                "<select baz=\"BazObjValue\" id=\"MyPrefix_foo\" multiple=\"multiple\" name=\"MyPrefix.foo\"><option>Alpha</option>" + Environment.NewLine
              + "<option>Bravo</option>" + Environment.NewLine
              + "<option>Charlie</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        [Fact]
        public void ListBoxForWithPrefixAndListOfSelectListItemSelectsDefaultFromViewData()
        {
            // Arrange
            ViewDataDictionary<FooModel> vdd = new ViewDataDictionary<FooModel> { { "foo", new string[] { "123456789", "111111111" } } };
            HtmlHelper<FooModel> helper = MvcHelper.GetHtmlHelper(vdd);
            helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix";

            // Act
            MvcHtmlString html = helper.ListBoxFor(m => m.foo, MultiSelectListTest.GetSampleListObjects());

            // Assert
            Assert.Equal(
                "<select id=\"MyPrefix_foo\" multiple=\"multiple\" name=\"MyPrefix.foo\"><option selected=\"selected\" value=\"123456789\">John</option>" + Environment.NewLine
              + "<option value=\"987654321\">Jane</option>" + Environment.NewLine
              + "<option selected=\"selected\" value=\"111111111\">Joe</option>" + Environment.NewLine
              + "</select>",
                html.ToHtmlString());
        }

        // Culture tests

        [Fact]
        [ReplaceCulture]
        public void SelectHelpersUseCurrentCultureToConvertValues()
        {
            // Arrange
            HtmlHelper defaultValueHelper = MvcHelper.GetHtmlHelper(new ViewDataDictionary
            {
                { "foo", new[] { new DateTime(1900, 1, 1, 0, 0, 1) } },
                { "bar", new DateTime(1900, 1, 1, 0, 0, 1) }
            });
            HtmlHelper helper = MvcHelper.GetHtmlHelper();
            SelectList selectList = new SelectList(GetSampleCultureAnonymousObjects(), "Date", "FullWord", new DateTime(1900, 1, 1, 0, 0, 0));

            var tests = new[]
            {
                // DropDownList(name, selectList, optionLabel)
                new
                {
                    Html = "<select id=\"foo\" name=\"foo\"><option selected=\"selected\" value=\"01/01/1900 00:00:00\">Alpha</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:01\">Bravo</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:02\">Charlie</option>" + Environment.NewLine
                         + "</select>",
                    Action = new Func<MvcHtmlString>(() => helper.DropDownList("foo", selectList, (string)null))
                },
                // DropDownList(name, selectList, optionLabel) (With default value selected from ViewData)
                new
                {
                    Html = "<select id=\"bar\" name=\"bar\"><option value=\"01/01/1900 00:00:00\">Alpha</option>" + Environment.NewLine
                         + "<option selected=\"selected\" value=\"01/01/1900 00:00:01\">Bravo</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:02\">Charlie</option>" + Environment.NewLine
                         + "</select>",
                    Action = new Func<MvcHtmlString>(() => defaultValueHelper.DropDownList("bar", selectList, (string)null))
                },
                // ListBox(name, selectList)
                new
                {
                    Html = "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option selected=\"selected\" value=\"01/01/1900 00:00:00\">Alpha</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:01\">Bravo</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:02\">Charlie</option>" + Environment.NewLine
                         + "</select>",
                    Action = new Func<MvcHtmlString>(() => helper.ListBox("foo", selectList))
                },
                // ListBox(name, selectList) (With default value selected from ViewData)
                new
                {
                    Html = "<select id=\"foo\" multiple=\"multiple\" name=\"foo\"><option value=\"01/01/1900 00:00:00\">Alpha</option>" + Environment.NewLine
                         + "<option selected=\"selected\" value=\"01/01/1900 00:00:01\">Bravo</option>" + Environment.NewLine
                         + "<option value=\"01/01/1900 00:00:02\">Charlie</option>" + Environment.NewLine
                         + "</select>",
                    Action = new Func<MvcHtmlString>(() => defaultValueHelper.ListBox("foo", selectList))
                }
            };

            // Act && Assert
            foreach (var test in tests)
            {
                Assert.Equal(test.Html, test.Action().ToHtmlString());
            }
        }

        // Helpers

        private class FooModel
        {
            public string foo { get; set; }
        }

        private class FooBarModel : FooModel
        {
            public string bar { get; set; }
        }

        private class NonIEnumerableModel
        {
            public int foo { get; set; }
        }

        private static ViewDataDictionary<FooBarModel> GetViewDataWithErrors()
        {
            ViewDataDictionary<FooBarModel> viewData = new ViewDataDictionary<FooBarModel> { { "foo", "ViewDataFoo" } };
            viewData.Model = new FooBarModel { foo = "ViewItemFoo", bar = "ViewItemBar" };

            ModelState modelStateFoo = new ModelState();
            modelStateFoo.Errors.Add(new ModelError("foo error 1"));
            modelStateFoo.Errors.Add(new ModelError("foo error 2"));
            viewData.ModelState["foo"] = modelStateFoo;
            modelStateFoo.Value = new ValueProviderResult(new string[] { "Bravo", "Charlie" }, "Bravo", CultureInfo.InvariantCulture);

            return viewData;
        }

        internal static IEnumerable GetSampleCultureAnonymousObjects()
        {
            return new[]
            {
                new { Date = new DateTime(1900, 1, 1, 0, 0, 0), FullWord = "Alpha" },
                new { Date = new DateTime(1900, 1, 1, 0, 0, 1), FullWord = "Bravo" },
                new { Date = new DateTime(1900, 1, 1, 0, 0, 2), FullWord = "Charlie" }
            };
        }

        private class RequiredModel
        {
            [Required]
            public string foo { get; set; }
        }
    }
}
