About me

Michael L Perry

Improving Enterprises

Principal Consultant

@michaellperry

User login

Michael L Perry's blog

Knockout JS and MVC Model Binding

Source code for this post is at https://github.com/MichaelLPerry/BuyMoreStuff.

Knockout is a great way to make interactive web pages using data binding and dependency tracking. Most of the uses of Knockout that I’ve seen use AJAX to send data to a RESTful JSON endpoint. But if you are using ASP.NET MVC, you don’t have to write another service if you don’t want to. You can take advantage of the powerful model binding that is built into the platform.

Interaction with observable arrays

Say you are building a shopping cart web page. You want your users to manage items in their cart all in the client, with no post-backs. Knockout is fantastic at this style of interaction. Just create a ko.observableArray in your view model, and add all of the cart lines to that array.

var ViewModel = function () {
    this.lines = ko.observableArray([
    @if (Model != null && Model.Cart != null && Model.Cart.Lines != null)
    {
        foreach (var line in Model.Cart.Lines)
        {
            var product = Model.GetProductById(line.ProductId);
            if (product != null)
            {
                @:new Line(this, @line.ProductId, "@product.Name", @product.UnitPrice, @line.Quantity),
            }
        }
    }
    ]);
};

The loop is generating JavaScript for all of the items already in the cart. So when the browser fetches the page, it is already fully populated. There is no second call to get the cart data.

Each of the lines in the array has an observable quantity, in addition to some immutable properties.

var Line = function (container, productId, productName, unitPrice, quantity) {
    this.productId = productId;
    this.productName = productName;
    this.unitPrice = unitPrice;

    this.quantity = ko.observable(quantity);

    this.remove = function() {
        container.lines.remove(this);
    }.bind(this);
}

To data bind these lines to a table, just use Knockout’s data-bind attribute.

        <table>

        <thead>
        <tr>
        <th>Product</th>
        <th>Quantity</th>
        <th>Price</th>
        <th>&nbsp;</th>
        </tr>
        </thead>

        <tbody data-bind="foreach: lines">
        <tr>
        <td>
            <input type="hidden" data-bind="value: productId" />
            <span data-bind="text: productName"></span>
        </td>
        <td><input type="text" data-bind="value: quantity" /></td>
        <td data-bind="text: unitPrice * quantity()"></td>
        <td><button type="button" data-bind="click: remove">-</button></td>
        </tr>
        </tbody>

        </table>

Notice the button data binding to the remove function so that the user can remove items from the cart.

Model binding

Now we need to get the modified cart data back on submit. Here’s where the model binder comes in. The MVC model binder looks for names on input fields to determine what properties to set. When the name refers to an element of a collection, the model binder creates an object and inserts it into the collection. We can use the Knockout “attr” syntax to set the name attribute of the inputs.

<input type="hidden" data-bind="value: productId, attr: {name: 'Cart.Lines[' + $index() + '].ProductId'}" />
<input type="text" data-bind="value: quantity, attr: {name: 'Cart.Lines[' + $index() + '].Quantity'}" />

Now when you submit this form, the MVC model binder will create a Cart object containing all of the items that the user managed on their client. This was all done through the standard MVC Razor view engine and model binder, with no additional AJAX calls.



KnockoutJS No Modification Allowed Error in Chrome

Test your KnockoutJS binding in all major browsers. If it just doesn’t appear to work, start the debugging console for that browser. Usually, this is F12.

I had a page that worked in IE. In Chrome, I saw “Uncaught Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7” in the console. Knockout was deep inside of ApplyBindings, but I couldn’t tell what the binding was. But by switching to the debug (non-minified) script, I was able to back up the stack a couple of calls to find that Knockout was trying to bind the “text” property on an input element.

There was my problem. I had:

<input type="text" data-bind="text: date" />

I needed to data bind “value”, not “text”.



Scaling collaborative applications with Azure and Correspondence

Azure is a great way to quickly deploy and scale your web sites. Correspondence is a rich framework for bringing collaborative experiences to multiple platforms. When these two come together, amazing things can happen.

The traditional web application has multiple stateless servers backed by a single database. You can scale out by adding new web servers, but this only goes so far if they all connect to the same database. Once you have saturated the database, where can you go?

The answer is to allow each web server to have its own local copy of the data, completely isolated from the other servers. Each new instance can serve requests without having to connect to an shared resource, like a SQL database. But how do you keep all of those local copies synchronized? That’s where Correspondence comes in.

imageCorrespondence

Correspondence is a collaborative application framework. It synchronizes data across several clients, including Windows Phone apps, WPF and Silverlight desktop apps, and Web sites. When you deploy a new instance of a Correspondence web site, it will pull down a copy of the application’s data locally. It serves all of its requests out of that local copy, so instances never compete for shared resources. And if the user changes the data on one server, it is pushed to all of the other servers so that they are kept up-to-date.

So where is that data coming from? And how is it being shared? At the heart of Correspondence is a distributor. Unlike a shared database, Correspondence applications don’t send every request to the distributor, so its load is much lighter. Instead, an application subscribes to the distributor. Each subscriber will receive changes as they occur. An application publishes data to the distributor, which in turn pushes it down to all of the other subscribers.

A web application instance is one such subscriber. When it receives data from the distributor, it stores it in the App_Data folder. Each Azure instance has its own App_Data folder. The Correspondence framework manages that App_Data folder and turns it into objects that the application can use.

MyCon

You can find an example of a Correspondence web application at https://github.com/MichaelLPerry/MyCon. Pull down the code using either Git or the Zip download link. You will need to enable NuGet Package Restore in order to build. This example app is running on Azure at http://awesomefest.azurewebsites.net/.

When you first run the solution, it will throw an exception indicating that you don’t have a conference ID. The exception contains a conference ID randomly generated for you. Just copy this conference ID into the web.config file and CommonSettings.cs.

MyCon is a template for a conference web site and phone application. It includes:

  • Silverlight 4 client for entering conference, speaker, and session data.
  • Web site for viewing that data.
  • Windows Phone application for attendees to use at the venue.

We will be concentrating on the web site. This project was built on MVC 3. It configures Correspondence to use the App_Data folder to store data. It also configures it to synchronize with an HTTP distributor. You will find that configuration in the SynchronizationService class:

public void Initialize()
{
    HTTPConfigurationProvider configurationProvider = new HTTPConfigurationProvider();
    string path = Path.Combine(HostingEnvironment.MapPath("~/App_Data"), "Correspondence");
    _community = new Community(FileStreamStorageStrategy.Load(path))
        .AddAsynchronousCommunicationStrategy(new BinaryHTTPAsynchronousCommunicationStrategy(configurationProvider))
        .Register<CorrespondenceModel>()
        .Subscribe(() => _conference)
        ;
}

The HTTP configuration provider loads the settings from web.config that identify the distributor:

    <add key="CorrespondenceAddress" value="https://api.facetedworlds.com/correspondence_server_web/bin" />
    <add key="CorrespondenceAPIKey" value="*******" />
    <add key="CorrespondencePollingIntervalSeconds" value="120" />

This distributor is hosted by my mobility company, Faceted Worlds. Feel free to use this host for your own instances of MyCon.

The last couple of lines of the configuration are registering the model and subscribing to the conference. This is where Correspondence is different from other frameworks. The model is only on the client, and the client subscribes to facts.

Facts

To make the data easier to distribute via publish/subscribe, Correspondence does not use a relational, document, or object-oriented model. Instead, it models data as historical facts. A historical fact is both a message and a record. As a message, it can be published and subscribed to. As a record, it can be queried.

The facts for the MyCon application are described in the file Model.fact. This file is located in the project FacetedWorlds.MyCon.Model under the WP7 folder. The other clients simply link to this one model. Facts are described as related data structures. For example:

fact RatingQuestion {
key:
    string text;
}

fact EssayQuestion {
key:
    string text;
}

fact Survey {
key:
    RatingQuestion *ratingQuestions;
    EssayQuestion *essayQuestions;
}

A fact can include references to other facts within its key. This acts like a foreign key in a relational database, allowing queries to join from the parent record to the child records. Parent facts are called “predecessors”, while child facts are called “successors”. That’s because predecessors come first in history.

In some cases the successor is published to its predecessor. For example:

fact ConferenceNotice {
key:
    publish Conference conference;
    time timeSent;
    string text;
}

When a successor is published, the application can subscribe to the predecessor. This will cause the distributor to push successors down to the application. In MyCon, each of the instances subscribes to the conference so that they all receive updates to conference data.

Deploy to Azure

Deploying a Correspondence web site to Azure is incredibly easy. First, sign up for an Azure account at http://windowsazure.com. Click on the “Portal” link and create a new Web Site. Use the “Quick Create” option. We won’t be creating a new web site with a database, since Correspondence will be our data store.

image image

Click on the arrow next to your application name to go to the application details. From here, click “Download publish profile”.

image

Back in Visual Studio, right-click on the FacetedWorlds.MyCon.Web project and select “Publish”. Click “Import” to import the publish profile that you downloaded from Azure. All of the settings that you need to publish your new site are copied into the dialog. Just click “Publish” and it will be uploaded for you. Once the site is published, it will open in a web browser.

Enter session data

Next, start up the FacetedWorlds.MyCon application in the Silverlight 4 folder. Using this application, you can enter a conference name, tracks, speakers, and sessions. Add rooms and times to the schedule grid, then drag the sessions onto the grid to arrange them.

As you enter data about the conference, it is published to the Correspondence distributor. The data is immediately pushed to all subscribers. Each Windows Phone running the conference app will subscribe to these changes. And so will each instance of the web site that you just deployed. Refresh the browser page to see that the web site has updated. It will serve the conference schedule from its own cache in App_Data. It does not need to hit a central database to serve a request.

Scale out

imageScaling out by adding new Azure instances is also extremely easy. Click on the “Scale” menu, move the slider over to allocate more instances, and then click “Save”.

When you add a new instance, it will subscribe to the conference. The distributor will send it all of the conference data entered so far. It will also set up a push notification channel for future changes. That way, whenever you change a session schedule using the Silverlight application, the change will be immediately reflected in the web application. It will be pushed to all instances of the web app so that they all remain synchronized.

Correspondence takes care of the hard problem of synchronizing data across independent instances of a web application. This allows the application to scale almost linearly as new instances are added. The instances don’t have a shared resource like a relational database that has to be available to respond to every request. Each instance can simply serve requests out of its own local copy in its App_Data folder.

Allocating new instances in Azure is a simple matter of moving a slider. As the big day approaches, ramp up the number of instances to handle new load. When the day has passed, ramp it back down to conserve resources. Correspondence and Azure are a powerful combination for creating scalable web sites.

For more information on how to build a Correspondence application, please visit http://correspondencecloud.com.



Delegates vs. Lambdas

What is the difference between these two lines of code?

bool anyNegative = numbers.Any(n => n < 0);

Vs.

bool anyNegative = numbers.Any(delegate(int n)
{
    return n < 0;
});

On the face of it, not much. These two lines do exactly the same thing. Yet there is an important difference.

The code inside of the lambda is an expression. The code inside of the delegate is a statement.

Expressions vs. statements

An expression computes a value, whereas a statement performs an action. In the above code, that action is to “return” a value. But the action could have been to change state. And therein lies the danger.

The order in which statements are executed is important. This is especially true if those statements change state. An assignment changes the state of a variable. A statement performed before the assignment sees the old value. A statement performed afterward sees the new value.

int m = 2;
Console.WriteLine(m);
m = 3;
Console.WriteLine(m);

Expressions, on the other hand, can be executed in any order, provided that they don’t change state. In the following code, it doesn’t matter if the program calculates x squared or y squared first. It will get the same answer because neither calculation changes state.

double x = 4.0;
double y = 3.0;
double h = Math.Sqrt(x * x + y * y);

Some expressions change state. For example, though the ++ operator increments a variable, it can be used as an expression. Also, a method called as part of an expression might in fact have some mutating side-effect. But in general, if we intend to change state, we will usually use a statement.

Delegates are commands; lambdas are queries

In Object-Oriented Software Construction, Bertrand Meyer defined a principle called “Command-Query Separation”. This principle encourages us to separate code that modifies state from code that computes values. A method that modifies state is a command, and should return void. A method that computes a value is a query, and should have no mutating side-effects.

If we follow this principle, then it will be difficult for us to write an expression that mutates state. If we avoid operators like ++ within our expressions, and we can’t call a void method, then we can safely assume that an expression is non-mutating. If our intent was to mutate state, we would have written a statement.

So if delegates contain statements, and the intent of a statement is to mutate state, then all delegates should be commands. Conversely, if lambdas contain expressions, and expressions can’t mutate state, then all lambdas should be queries.

To make your intention clear, use lambdas to compute values, and delegates to make changes.

public ICommand Delete
{
    get
    {
        return MakeCommand
            .When(() => _selected != null)
            .Do(delegate
            {
                _selected.Delete();
            });
    }
}


Correspondence on Android

Correspondence_AndroidBuilding an Android app that stands out from the Marketplace crowd is not easy. The experience has to be worth talking about. And the app needs to give people a reason to share. If the app is unresponsive or frustrating, people aren’t going to use it. And if it doesn’t connect people, they aren’t compelled to talk about it.

Correspondence is a collaboration framework. It solves the technical problems related to building mobile apps that connect people. It provides local storage on the device, synchronization across devices, push notifications, and UI updates.

And now Correspondence is available on Android.

Build compelling collaborative experiences

Most of the apps that you find in the Android Marketplace are single-player games or single-user utilities. They store one person’s data on one device, and are designed for one user to enjoy. They are experience silos.

Mobile web applications, on the other hand, let users share information with one another. But they come with a cost. Most of them don’t store personal information locally, so you have to sign in to the server every time you use the app. And when you have a slow or intermittent data connection, the experience can suffer.

To make your app stand out from the Marketplace crowd, make it collaborative. A collaborative app lets users share information like a web app, but it also stores personal information on the device. Users get the advantage of a quick response regardless of the data connection, since all of the data that they have shared with others is stored locally. But they also get the advantage of being able to connect with their friends, since the collaborative application tears down the silos.

Phones are collaborative devices. An app should be a collaborative experience.

Focus on the client; we’ll handle the server

If you were to develop a collaborative application using traditional stacks, you would have to build a server-side database. Then you would build an API to access that database, probably using REST endpoints and JSON serialization. You would find a host, deploy the database and the code, and perhaps install an SSL certificate for secure communications. And whenever you add a features to your app, you’ll need to migrate the database and redeploy the code.

Correspondence is different. It is a single, application-agnostic server. It is schemaless, so there are no database scripts to deploy. And it has a single publish/subscribe API that can be used for any type of information. All you do is sign up for an API key, and build your app.

Download the project from GitHub. Follow the provided instructions to set up an Eclipse workspace and build the HoneyDo List example application.



Provable Code course on Pluralsight

Please check out my Provable Code course on Pluralsight. If you are not yet a Pluralsight subscriber, go ahead and sign up for 200 free minutes. You won’t be able to get through the whole course on that, but it will be enough for you to decide whether to subscribe.



You’re Invited publish subscribe

The reason for using Correspondence was to make it easy to share data between the phone and the web. Here's a few unit tests that show how the web subscribes to data published on the phone.



You’re Invited Correspondence model

In this video, I create the Correspondence model for the You're Invited application, and start a set of unit tests. The templates start off with a working model, and I just tweak it to create the app I need.



You’re Invited Windows Phone 7 app

A couple of months ago, my friends and I started a Windows Phone 7 application called You're Invited. It took first prize at the contest, but we didn't actually complete it. This weekend, I'm going to finish it up so we can get it in the Marketplace.



MyCon: Web and Windows Phone template for conferences

If you are organizing a conference and need to build a web site for you attendees, feel free to use this template. If you want to give conference-goers a Windows Phone 7 application to organize their schedule, this template is yours.

MyCon is an ASP .NET MVC, Silverlight, and Windows Phone application that you can customize to run your own conference web site and mobile app. The code is free and open source. You just cover your own hosting.

The web site

Your conference web site lists your speakers, complete with photo and bio. Click on a speaker’s name to see all of the sessions that they are presenting.

image  image

Or break down sessions by track or by schedule. Please see the demo site.

The Windows Phone app

Your attendees will use their Windows Phones to manage their own schedule. They can browse sessions by time slot, speaker, or track, and can even search.

Schedule  Tracks  Search

The scheduling app

Use the Silverlight application to enter speaker, session, and schedule data. Everything you enter is synchronized to the web site and the phone app.

Conference

How to use the template

It’s easy to use the template. Simply fork the git repository and start making your changes. Here are the changes you need to make to the web app.

  1. Create a database in SQL Express called “MyCon”. The application will initialize it for you. If you don’t use SQL Express, edit the connection string in web.config.
  2. Enter a Conference ID in CommonSettings.cs. Just run the application and it will generate a new ID for you.
  3. Enter your own content in Views/Home/Index.cshtml and Views/Sponsors/Index.cshtml.
  4. Add your own banner to Views/Shares/_Layout.cshtml.
  5. Deploy the web application to AppHarbor, Azure or your own hosting provider. If you use AppHarbor, choose the SQL Server add-on.
  6. Run the Silverlight 4 application to create your session schedule.

And here are the changes you need to make in the Windows Phone app.

    1. Replace the images (ApplicationIcon.png, Background.png, and SplashScreen.png).
    2. Change the settings in WMAppManifest.xml (generate a new GUID for ProductID, set the Title, Author, Description, and Publisher).

Once you are ready to publish, you can pre-load the conference schedule so attendees don’t have to download it when they first use the app.

  1. Run the Capture desktop application.
  2. Copy the binary files that it generates from C:\Users\user\AppData\Roaming\FacetedWorlds\MyCon to the Data folder in the WP7 project.

If you change the schedule after you publish, don’t worry. The app will automatically download the updates.

Give back

You are free to use this template for any purpose. If you love it, there are many ways that you can give back.

  • Make a suggestion on how to improve the template.
  • Send me a git pull request on improvements that you have already made.
  • Tweet a link to this page (copy me @michaellperry).
  • Help someone else set up their conference app.
  • Include the “Powered by Correspondence” logo on your app’s splash screen.

image