Preserving Whitespace in DropDownList Items with C# MVC 3

Recently I noticed that the whitespace of the text on my pages wasn’t being preserved when the page loaded. Then I was reminded that, generally, multiple spaces get collapsed and text will wrap when it’s necessary. If you want to change this behavior then you’ll need to reach for the white-space CSS property.

No problem. I updated my text such that white-space:pre-wrap got applied and everything seemed great. Until I saw that my select lists completely ignored the change.

Awesome. After some some digging around and talking to a colleague for a few minutes we determined that the text that’s intended to appear between the option tags of the select list needs to be sent as decoded HTML.

To accomplish this we used a combination of string.Replace and HttpServerUtility.HtmlDecode(string s). The idea is that for any given string that has multiple whitespaces between characters where the displayed text must match the specified text then the whitespaces need to be replaced with   (non-breaking spaces) and then converted on display such that the whitespaces are preserved and the text is displayed correctly.

Here’s the key line: return HttpContext.Current.Server.HtmlDecode(<string>.Replace(" ", "&nbsp;"));

Here’s the working example:

Item.cs (Model)

namespace Site.Models
{
    using System.Web;

    public class Item
    {
        public Item() { }

        public string DecodedName
        {
            string result = string.Empty;
            if(!string.IsNullOrEmpty(this.Name))
            {
                result = HttpContext.Current.Server.HtmlDecode(this.Name.Replace(" ", "&nbsp;"));
            }

            return result;
        }

        public int Id { get; set; }

        public string Name { get; set; }
    }
}

Index.cshtml (View)

@using Site.Models
@model IEnumerable<Item>

@{ Layout = null; }
<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    @this.Html.DropDownList("MyList", new SelectList(this.Model, "Id", "DecodedName"), string.Empty)
</body>
</html>

HomeController.cs (Controller)

namespace Site.Controllers
{
    using System.Collections.Generic;
    using System.Web.Mvc;
    using Site.Models;

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            IEnumerable<Item> model = this.BuildModel();
            return this.View(model);
        }

        private IEnumerable<Item> BuildModel()
        {
            ICollection<Item> result = new List<Item>
            {
                new Item { Id = 1, Name = "Item 1" },
                new Item { Id = 2, Name = "Item     2" },
                new Item { Id = 3, Name = "Item          3" },
                new Item { Id = 4, Name = string.Empty },
                new Item { Id = 5, Name = null },
            }

            return result;
        }
    }
}

Here is the rendered HTML…

Select with Whitespace Preserved… And here is the page source

Page Source for Whitespace Preserving Select