How to add dynamically populated selects/dropdowns to a basic asp.net MVC site?

Here's an example control group for a drop down list that is dynamically populated from a JSON service

<div class="control-group">
    @Html.LabelFor(m => m.Responsible, new { @class = "control-label" })
    <div class="controls">
        @Html.DropDownListFor(m => m.Responsible, Model.CurrentResponsibleItem, new { @id = "Responsible", @style = "width:300px;" })
        @Html.ValidationMessageFor(m => m.Responsible, null, new { @class = "help-inline" })
        <a href='~/Help/Responsible' target="_blank">help <span class="glyphicon glyphicon-new-window"></span></a>
    </div>
</div>

And here's the javascript to be called in document.ready:

var personUrl = '/SomeUrl/GetPerson';
var pageSize = 20;
$('#TargetControlID').select2({
    placeholder: 'Responsible person',
    //Does the user have to enter any data before sending the ajax request:
    minimumInputLength: 3,
    allowClear: true,
    ajax: {
        //How long the user has to pause their typing before sending the next request
        quietMillis: 150,
        //The url of the json service
        url: personUrl,
        dataType: 'jsonp',
        //Our search term and what page we are on
        data: function (term, page) {
            return {
                pageSize: pageSize,
                pageNum: page,
                searchTerm: term.term
            };
        },
        results: function (data, page) {
            //Used to determine whether or not there are more results available,
            //and if requests for more data should be sent in the infinite scrolling
            var more = (page * pageSize) < data.Total;
            return { results: data.Results, more: more };
        }
    }
});

Note the part above where it says "term.term" I discovered i needed that while debugging, like a primitive cave dweller.

These two DTO classes are used on the server, for sending json back to select2 in a form it expects.

public class Select2OptionModel
{
    public string id { get; set; }
    public string text { get; set; }
}

public class Select2PagedResult
{
    public int total { get; set; }
    public IEnumerable<Select2OptionModel> results { get; set; }
}

Here's the method which is called by the client-side ajax, when searching for an item.

(This is v ugly code, I didn't prepare it for re-use at all. This example fetches people records from a table, and projects them into Select2OptionModels, which are then packed into a Select2PagedResult for use by select2. Ahhh... I have ignored the pageNum and pageSize too, by the looks of it. I didn't even need to worry about them for the size of my data (thousands not millions of rows))

    [HttpGet]
    public ActionResult GetPerson(string searchTerm, int pageSize, int? pageNum)
    {
        if (string.IsNullOrWhiteSpace(searchTerm) || searchTerm.Trim().Length < 3)
        {
            return new JsonpResult
            {
                Data = null
            };
        }

        IEnumerable<Select2OptionModel> people;

        using (var connection = new ProfiledDbConnection(SqlConnectionString.GetOpenConnection("DB"), MiniProfiler.Current))
        {
            people = connection.SelectWhere<Person>("Name like @searchTerm and not ActiveDirectoryID is null",
               new { searchTerm = "%" + searchTerm.Replace(" ", "%") + "%" })
               .Select(p => new Select2OptionModel {
                    id = p.ActiveDirectoryID,
                    text = p.Name });
        }

        Select2PagedResult result = new Select2PagedResult { total = people.Count(), results = people };

        //Return the data as a jsonp result
        return new JsonpResult
        {
            Data = result
        };
    }

That is all so lengthy, so filled with ceremony... it's not the fun-filled code we were hoping for. Sorry.

Source