A Better SelectList for ASP.Net MVC

The following is a more complete version of the code I posted as an answer to a Stack Overflow question. The purpose is to provide a statically typed method for creating a SelectList. If you work with ASP.NET MVC, you will have encountered these. This version of the code has more overloads to make it that much easier to set selected values, which is especially handy when using a multiple-selection drop-down box. You can specify a boolean to make all options selected or not, or pass a single value (string or int) or an array of values that correspond to the items you want selected.

The benefit of making it statically typed is that you’ll catch errors at design-time that would have otherwise occurred at run-time. To create a SelectList previously required passing string values representing property names that could be incorrect or misspelled, which goes unnoticed by the compiler. An error would not occur until a user tried to view your page.

The complete ToSelectList method listings follow the usage examples because it is quite lengthy.

Usage example in a controller action:

var myCompanies = new[] { "ABC", "XYZ" };
ViewBag.CompanyList = db.Companies.ToSelectList(j => j.CompanyCode, j => j.CompanyName, myCompanies /*selectedValues*/);
ViewBag.JobList = db.Jobs.ToSelectList(j => j.JobCode, j => j.JobDesc, true /*selectAll*/);

And subsequent usage in a view (razor syntax):

@Html.DropDownList("companies", ViewBag.CompanyList as IEnumerable<SelectListItem>, null, new { multiple = "multiple", size = "5" })
@Html.DropDownList("jobs", ViewBag.JobList as IEnumerable<SelectListItem>, null, new { multiple = "multiple", size = "10" })

This would result in two select elements allowing multiple selections. The first, Companies, would have companies with CompanyCodes “ABC” and “XYZ” selected. (If companies don’t exist for one or more of the given values, it is simply skipped and no error is thrown–a good thing.) The second, Jobs, would initially have all of the values in the list selected since we passed true for the selectAll parameter.

ToSelectList.cs with inline documentation for each overloaded method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

public static partial class Helpers {

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value) {
    return enumerable.ToSelectList(value, value, false);
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValue">The selected value.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, int selectedValue) {
    return enumerable.ToSelectList(value, value, new string[] { selectedValue.ToString() }.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValue">The selected value.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, string selectedValue) {
    return enumerable.ToSelectList(value, value, new string[] { selectedValue }.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, int[] selectedValues) {
    if (selectedValues == null) {
      throw new ArgumentNullException("selectedValues");
    }
    return enumerable.ToSelectList(value, value, selectedValues.ToList().ConvertAll<string>(i => i.ToString()));
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, IList<int> selectedValues) {
    return enumerable.ToSelectList(value, value, selectedValues.Cast<string>().ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, string[] selectedValues) {
    return enumerable.ToSelectList(value, value, selectedValues.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, IList<string> selectedValues) {
    return enumerable.ToSelectList(value, value, selectedValues);
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and the data text field.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text) {
    return enumerable.ToSelectList(value, text, false);
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValue">The selected value.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, int selectedValue) {
    return enumerable.ToSelectList(value, text, new string[] { selectedValue.ToString() }.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValue">The selected value.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, string selectedValue) {
    return enumerable.ToSelectList(value, text, new string[] { selectedValue }.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and the selected values.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, int[] selectedValues) {
    if (selectedValues == null) {
      throw new ArgumentNullException("selectedValues");
    }
    return enumerable.ToSelectList(value, text, selectedValues.ToList().ConvertAll<string>(i => i.ToString()));
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and the selected values.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, IList<int> selectedValues) {
    return enumerable.ToSelectList(value, text, selectedValues.Cast<string>().ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and the selected values.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, string[] selectedValues) {
    if (selectedValues == null) {
      throw new ArgumentNullException("selectedValues");
    }
    return enumerable.ToSelectList(value, text, selectedValues.ToList());
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and the selected values.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectedValues">The selected values.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, IList<string> selectedValues) {
    foreach (var f in enumerable) {
      yield return new SelectListItem() {
        Value = value(f),
        Text = text(f),
        Selected = selectedValues.Contains(value(f))
      };
    }
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field and a selected value.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="selectAll">Whether all values are selected.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, bool selectAll) {
    return enumerable.ToSelectList(value, value, selectAll);
  }

  /// <summary>
  /// Returns an IEnumerable&lt;SelectListItem&gt; by using the specified checkboxes for data value field, the data text field, and the selected values.
  /// </summary>
  /// <param name="enumerable">The checkboxes.</param>
  /// <param name="value">The data value field.</param>
  /// <param name="text">The data text field.</param>
  /// <param name="selectAll">Whether all values are selected.</param>
  public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, bool selectAll) {
    foreach (var f in enumerable) {
      yield return new SelectListItem() {
        Value = value(f),
        Text = text(f),
        Selected = selectAll
      };
    }
  }

}
Programming , , , ,
  • Trung Lee

    Thanks very much ! but i want display as : two Text replace one Text, such as : ToSelectList(value, text1, text2, selectedValues.ToList());
    How to do this work?

  • HeavyDrinker

    Do you consider ViewBag to be strongly typed?

    • Justin Stolle

      No.