Knockout.js is a javascript library that allows us to bind html elements against any data model. It provides a simple two-way data binding mechanism between your data model and UI means any changes to data model are automatically reflected in the DOM(UI) and any changes to the DOM are automatically reflected to the data model.

Based on ASP.NET, ASP.NET MVC allows software developers to build a web application as a composition of three roles: Model, View and Controller. The MVC model defines web applications with 3 logic layers: The business layer (Model logic),The display layer (View logic),The input control (Controller logic).

This article will demonstrate how to load a KnockoutJS view model from a C# controller using ajax in an ASP.NET MVC project. I’m just going to jump straight into the code for this sample.  To get started we need to create a new action in the controller.  For the purposes of this sample this action will return a randomly populated Person object (see the previous articles for the definition) so that we can see the content changing.  Here is the action:

public class SampleController : Controller
{
    public ActionResult AjaxModelLoading()
    {
        Person model = CreateRandomModel();
        if (Request.IsAjaxRequest())
        {
            return new JsonNetResult(model);
        }
        return View(model);
    } 
    private static Person CreateRandomModel()
    {
        Random random = new Random();
        string[] firstNames = { "Billy", "Kevin", "Michael", "Steve" };
        string[] lastNames = { "Jordan", "Smith", "Wild", "Walker" };
        string firstName = firstNames[random.Next(firstNames.Length)];
        string lastName = lastNames[random.Next(lastNames.Length)]; 
        return new Person
        {
            FirstName = firstName,
            LastName = lastName,
            EmailAddress = string.Format("{0}@{1}.com", firstName, lastName),
            PhoneNumber = random.Next(int.MaxValue).ToString("D10"),
            DateOfBirth = DateTime.Today.AddYears(random.Next(-50, -10))
        };
    }
}


This action creates the Person object and then detects if the HTTP request was made using ajax.  If it was then it serializes the model as JSON and if it is a standard HTTP request it returns the view.  This is a handy technique for implementing a simple refresh of data in the view without retrieving all the HTML from the server again.

On line 9 you can see that I have not used the standard ASP.NET JSON serializer.  Instead I went with my own ActionResult which makes use of JSON.NET to give myself more control over the generated JSON.  For reference the code for my JsonNetResult class is below:
public class JsonNetResult : ActionResult
{
  
    private const string ContentType = "application/json"; 
    private readonly object data;
    private readonly Formatting formatting;
    private readonly JsonSerializerSettings serializerSettings; 
    public JsonNetResult(object data)
    {
        this.data = data;
        formatting = Formatting.None;
        serializerSettings = new JsonSerializerSettings
       {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }
    public override void ExecuteResult(ControllerContext context)
    {
        HttpResponseBase response = context.HttpContext.Response;
        response.ContentType = ContentType;
        if (data != null)
        {
            JsonTextWriter writer = new JsonTextWriter(response.Output) { Formatting = formatting };
            JsonSerializer serializer = JsonSerializer.Create(serializerSettings);
            serializer.Serialize(writer, data);
            writer.Flush();
       }
    } 
    public object Data
    {
        get { return data; }
    }
}


Next we need to create the KnockoutJS view model to bind to the view.
var AjaxModelLoading = function(url) {
    var self = this;
    self.isLoaded = ko.observable(false);
    self.isLoading = ko.observable(false); 
    self.getRandomModel = function () {
        self.isLoading(true);
        self.isLoaded(false);
 
        // Setting a timeout so the loading text is visible in the sample
        setTimeout(function() {
            $.ajax(url, {
                type: "GET",
                cache: false,
            }).done(function(data) {
                ko.mapping.fromJS(data, {}, self);
                self.isLoaded(true);
                self.isLoading(false);
            });
        }, 1000);
    };
};


This view model defines a function which will be used to handle a click event from the view in order to refresh the data. It also does some basic state management to determine if the content has been loaded or is in the process of loading.  I have put in a short delay between the click in the view and executing the ajax request in order to make the loading state management more apparent for the sample.

Lastly we need to create the view.
@model Quickstart.Web.Models.Person 
@section scripts
{
    <script type="text/javascript" src="/Scripts/ViewModels/AjaxModelLoading.js"></script>
    <script type="text/javascript">
        var viewModel = new AjaxModelLoading("@Url.Action("AjaxModelLoading")");
        ko.applyBindings(viewModel); 
        viewModel.getRandomModel();
    </script>
}
 
<h2>Ajax Model Loading Sample</h2>

<div data-bind="if: isLoading()">
    Loading...
</div>
 
<div data-bind="if: isLoaded()">
    <div>
        <label>First Name:</label>
        <input type="text" data-bind="value: firstName"/>
    </div>
 
    <div>
        <label>Last Name:</label>
        <input type="text" data-bind="value: lastName"/>
    </div>

    <div>
        <label>Email Address:</label>
        <input type="text" data-bind="value: emailAddress"/>
    </div>
 
    <div>
        <label>Phone Number:</label>
        <input type="text" data-bind="value: phoneNumber"/>
    </div>
 
    <div>
        <label>Date of Birth:</label>
        <input type="text" data-bind="value: dateOfBirth"/>
    </div>
</div>
<a href="#" data-bind="click: getRandomModel">Get random person</a>