Migrating a Silverlight application to HTML5 - part I

Sun Sep 28 2014

Browser-based plug-in applications are rapidly losing market in favor of open standards. One of the first and biggest facts in that line was made by Apple Inc. about Flash support. In April 2010 Steve Jobs published an open letter explaining why Apple would not allow Flash on the iPhone, iPod touch and iPad. It was a big announcement on those days, in favor of open standards for the Web.

Back in 2007, Microsoft announced the Silverlight platform, a development tool for creating Rich Internet Applications (RIA). It runs on client side as a plug-in using the Netscape Plug-in Application Programming Interface NPAPI. Basically Silverlight was a competitor for Flash RIA applications made in ActionScript. The big advantage of Silverlight is the .Net framework and their Visual Studio IDE. With .Net you can have a beautiful application, coded in the same language as most of your applications and with almost the same characteristics (C#, Visual Basic, Linq, XML literals). Plus, you can have support for Linux with the Moonlight project.

One of the drawbacks of Silverlight is that it's not an open standard (the same problem with Flash, announced by Steve Jobs back in 2010). Certainly it's a cross browser platform, but as long as you install the Silverlight plug-in for it. And for the UI definition Microsoft uses XAML, which goes one step further in closed proprietary standards. Considering this, it's obvious that at some point the industry will decide to throw out XAML standards, in favor of HTML and Javascript for front end development.

The history is well known: Since the release of Silverlight 5 in December 2011 there has not been any active development in the platform. Microsoft announced in their Microsoft Support Lifecycle that Silverlight 5 will have support until 10/12/2021. Now the Chromium project announced on September 23, 2013 the deprecation of NPAPI plug-ins. This means that in the next months Chrome will drop Silverlight support on Chrome. First starting with a warning, then through a more aggressive advice, and finally by the end of 2014, without support (more information here).

This is a very big problem for software companies that trusted their new products on this technology; the investment in training for developers in a technology which lasted less than five years is worrying, to say the least. Another issue to take into account is the multi browser support: there is no Silverlight plugin for Android or iOs on tablets and smartphones (only on Windows Phones, which has a very little part on the market share). That means that the customers are reduced to the PC market, a decreasing share since the rise of tablets and cloud web based applications.

The alternative

Considering the points explained in the last section, there is a big chance for technology migration, from Silverlight applications to more open standards with HTML and Javascript. Is HTML and Javascript mature enough to allow the same UI behaviour than with XAML/Silverlight? We'll see.

Silverlight/MVVM pattern

One of the most important patterns in Silverlight is Model-View-ViewModel. MVVM is a specialization of the Presentation Model pattern. The Presentation Model says that there is a model that represent the state and behaviour of the presentation, independently of the GUI controls used in the interface.

MVVM facilitates a clear separation of the UI from the business logic:

MVVM

As you can see, the MVVM pattern is composed of two relations:

  • The View-ViewModel: implements the Presentation Model pattern. The View is bounded with properties of a ViewModel, in a one-way or two-way binding. That means that the UI can present to the user the state of a ViewModel (one-way). Also, it allows to change the state of the ViewModel when the user changes something from the UI, or that any change in the ViewModel implies a refresh on the affected bounded UI (two-way).

  • The ViewModel-Model: the ViewModel serves as an intermediary between the UI and the Model. It takes the data from the Model and translates it to the UI.

Here is an example of a binding between the UI and the ViewModel:

MVVM2

In the image, the XAML UI has a TextBlock element associated with the Giro property of the ViewModel. The Giro property is a String in the ViewModel class. As the binding is a two-way binding, a change in the Giro property reflects a change in the UI. In the same way, a change in the UI on that control reflects a change in the Giro property.

HTML/MVVM pattern

There are a lot of javascript frameworks or libraries that implements the MVVM pattern. In this article, I'm going to show Knockout for this purpose. The reasons are:

  1. Knockout is a tiny library that implements the MVVM pattern.
  2. Whilst other frameworks implements MVC, MVVM, hash routing and so on, Knockout just has his focus on MVVM. This alleviate the overload of unnecessary techniques.
  3. The library is very mature, with good resources on his page.
  4. You can add UI effects with whatever library you want through bindinghandlers.
  5. It's easy to package a UI with components.

Knockout does not have all the properties of SPA frameworks like AngularJS or Durandal. That doesn't means you cannot create SPA applications with Knockout.

Here is an excellent video from Steve Sanderson (creator of the knockout library) in which he explains how to develop SPA applications with Knockout + CrossRoadJs + RequireJs. It has a lot of useful information, in case you're starting to work with SPA applications, or with single pages that needs dynamic user interaction.

Steve Sanderson - Architecting large Single Page Applications with Knockout.js from NDC Conferences on Vimeo.

In Knockout you define an HTML element and add the data-bind property to define the binding between the View and the ViewModel. The ko.observable() defines a two-way binding for simple properties (or complex objects), and the ko.observableArray() defines a two-way binding for list of objects:


    <input data-bind="value: Giro"/>
    <div>The value for the property is: <span data-bind="text: Giro"/></div>
    <ul data-bind="foreach: Persons">
        <li data-bind="text: Information"/>
    </ul>

    function ViewModel()
    {
        this.Giro = ko.observable("Hello, World");
        this.Persons = ko.observableArray();
        this.Persons.push(new PersonViewModel("John", "Wayne", 33));
        this.Persons.push(new PersonViewModel("Homer", "Simpson", 29));
        this.Persons.push(new PersonViewModel("Clint", "Eastwood", 23));
    }

    function PersonViewModel(firstName, lastName, age)
    {
        var self = this;
        this.FirstName = ko.observable(firstName);
        this.LastName = ko.observable(lastName);
        this.Age = ko.observable(age);
        this.Information = ko.computed(function() {
            return self.FirstName() + " " + self.LastName() + ", " + self.Age();
        });
    }

    ko.applyBindings(new ViewModel());

The result: (JsFiddle link)

MVVM4

The input element is associated with the Giro property, the same as the spam element. If you type on the input element the span changes also. That's the two-way binding (also if you change the Giro property in javascript the UI gets refreshed.).

Silverlight/WCF services

The communication between the client application in Silverlight and the server, where the business logic resides, is made with WCF services. Remember that the ViewModel is a representation of the Model which resides on the server in this case. WCF is very similar to Web Services. Some of the differences are:

  • WCF serializes with the DataContractSerializer class that's based on XmlObjectSerializer. This serialization allows to define which properties of the class can be serialized and it has better performance than the XmlSerializer.

  • There are classes that cannot be serialized through Web Services that WCF can, for example HashTable.

  • Web Services can be consumed only through HTTP, whilst WCF uses a lot of other network protocols.

Once you have your ViewModel on certain state and you want to execute a command with it (say, save a ViewModel, for example) you need to convert the ViewModel to a DataContract class. Once done, you can send the DataContract class to the server through WCF, where it converts the class (if apply) to a Business Model, executes the changes and then informs to the client that the execution was made.

MVVM3

In the image you can see the rendered button and his XAML definition. The XAML defines an event, GuardarCommand that executes the Guardar() method. This method calls to convert the ViewModel object to a DataContract object, which is a parameter for the WCF method on the server side. Once finished the execution call, there is a delegate event handler which processes the result, if any.

HTML/Ajax Calls

An async call in HTML works in the same way as a WCF call:

Silverlight HTML
Define a command event for the Silverlight control Define an event handler for the HTML element
Delegates the event to another method Can delegate the event or apply an inline function
Converts the ViewModel to a DataContract Converts the Javascript ViewModel to a JSON object
Call the WCF service, in a sync or async way. Executes a delegated event when the service finish. Call a Web Service or a Restfull service. Can delegate to another function or define an inline function.

It depends on the server, but the async calls are practically all the same. here is an example of a call for a WebMethod in ASPX using jQuery:


    $.ajax(
    {
      type: 'POST',
      url: '../My.aspx/MyWebMethod',
      data: JSON.stringify(my_Javascript_Object),
      contentType: 'application/json; charset=utf-8',
      dataType: 'json',
      success: function(data) { 
        // here I process the return
      },
      error: function(data) {
         // here I process when the call failed
      },
    });

Silverlight/UserControls

If you have a UI that needs to be used in more than one part of an XAML, or maybe in more than one XAML, you can create a UserControl. A UserControl is nothing but a XAML with his own behaviour. It's a packaged control that can be used in several parts of the project. For an example, please see this link

HTML/Components

Knockout.js also provides the creation of UserControls. It's a new feature of the 3.2.0 version, released on August 18, 2014, so we can say that this new feature allow us to register UserControls in the same way as Silverlight. It was one of the required features to scale and structure large applications. In this example, you can see how we define one single component, using it five times in the HTML:


    <greeting-name></greeting-name>
    <greeting-name></greeting-name>
    <greeting-name></greeting-name>
    <greeting-name></greeting-name>
    <greeting-name></greeting-name>    

    ko.components.register("greeting-name", {
    viewModel: function(params) {
        var self = this;
        this.Name = ko.observable();
        this.Greeting = ko.computed(function() {
            if(self.Name())
                return "Hello " + self.Name();
            else
                return "";
        });
    },
    template: 'Enter name: <input data-bind="value: Name"/><div data-bind="text: Greeting"/>'
    });
    ko.applyBindings();

The result: (JsFiddle link)

MVVM5

You can use RequireJS and the text plugin to get the component template from an isolated html file. I will talk about Asynchronous module definition in another article, but it's a method in which you define your function or functions and the dependencies that their needs to start. RequireJS then starts and check the dependency graph, ensuring that your module doesn't start until all the dependencies are loaded. For example:


    <!-- myTemplate.html -->
    <div>Here is my template for the ViewModel</div>

// MyViewModel.js
define(['knockout', 'text!./myTemplate.html'], function(ko, templateMarkup) {

    function MyViewModel(params) {
        // MVVM definition
    }
    return { viewModel: MyViewModel, template: templateMarkup };
});

In this case we are defining a knockout component with RequierJS. The library then detects that this javascript needs first to load knockout and the HTML template. Once done, it executes the ViewModel definition and send the control to another function that needs it, like the main function where you register the component.

Where to begin

Suppose you have a Silverlight application that's often used by tons of clients. You cannot just stop the application, wait several months until migrated, and then plug in the new UI. That's not possible. So, we have to apply a simple migration alternative.

My employer asked me to investigate how much does cost to migrate a Silverlight application to HTML. Because Knockout implements the MVVM pattern, and jQuery allows me to make async calls like with WCF, I can practically start to migrate in a copy and paste way:

  • Look the XAML and create their corresponding HTML elements. If there is an UserControl, create a component.

  • Look the binding in the XAML and the property of the ViewModel. Create a ViewModel with knockout, using ko.observable for properties and ko.observableArray for collections.

  • Check the XAML commands and create their corresponding function in the ViewModel. If there is a WCF call, make the same with jQuery ajax.

First impressions

In the practice it's not as easy as it looks, sadly. One of my first problems was to deal with WCF on Ajax calls. As far as I know, you cannot just use the same WCF services to get JSON objects, so I created ASPX [WebMethod] that calls WCF from assembly and returns the result. This worked like a charm, but makes me to depend heavily on ASPX: compile, check, test, etc. So I founded an excellent library jquery-mockjax that allows me to mock Ajax calls. Then I just define the server calls and used the library to mock the result.

The DateTime object in Javascript is very complex. I think it's going to make a lot of noise to my developments. That's because the application uses dd/mm/yyyy format and the parsing between dates seems very difficult and inexpressive. Happily I see the Moment.js library that allows to parse and manipulate dates. I have no experience with it, hope it can be the final solution to the date problem.

Other issues are more related with UI designs. Silverlight has a lot of good resources for UI that makes development very straightforward: autocomplete, grids with filters, UI effects, etc. I'm not really sure if I can find similar implementations for every UI design in HTML. I know that jQuery UI has a lot of widgets, but they are very ugly and add a lot of DOM elements to my HTML, without taking into account display resolutions. Anyway, bower seems a good starting point for UI widget search.

Another issue was the use of Visual Studio. Our Silverlight application has one ASPX that initiates the Silverlight. I started creating my ASPX with HTML and knockout components, but Visual Studio is not as light as I wanted. So, my first move was to change temporarily the development environment. This is my recommendation:

Download and install Node.js, Yeoman and Bower Bower is an excellent tool for Web dependencies. It's like Nuget package management, but you can add libraries from almost any GIT repository.

Use Sublime Text 2 for coding and Visual Studio for Silverlight. Sublime Text is very fast and has a lot of automatization.

Throw away CSS Frameworks like Bootstrap or Foundation and start using Less or Sass. This is a very important topic that maybe I can explain later. I'm always checking the new CSS Frameworks, looking for a very good one. I sincerely don't understand how we devolutioned again to bad HTML designs:

  1. At the beginning we had a lot of HTML mixed with UI properties (border, cellpadding, cellspacing, style="...", etc.). Some Web experts told us that it's a mistake, and that we needed to focus on the structure and content, leaving the display to CSS.
  2. We adopted good separation between content and display with clean HTML and CSS files.
  3. We started to see the community claiming for more semantic HTML, in order to forget tables and stuffs, focusing on the content of the Web. That's the evolution of Web and it was good.
  4. Don't know when but at some point there appeared a lot of CSS frameworks, talking about responsive design, filling the HTML with a lot of classes like red col colg 80x right up float left jump smile one two three. But hey!! it's not the same as the old input style="style-with-a-lot-of-stuffs" because now we have classes. What a joke!.

With Less or Sass you can take advantage of the new semantic HTML5 tags and focus on the content, leaving for real the UI to the CSS. I'm using Less and Responsable CSS for the basic CSS processing. Responsable CSS is a simple CSS library that allows to get an initial HTML page. With this, their mixins and your semantic definition you can start thinking in content first, defining the UI later. Responsive design? Sure, you can take advantage of CSS3 media queries and maybe some Javascript is you need to. Try to apply your own CSS styles, not from others.

Start with a single page application (SPA) using knockout yeoman scaffolding (yo ko)

I strongly recommend to check the Steve Sanderson video. It's very inspiring and shown me a lot of things new to me, specially how to accelerate the Web development.

One of my first fears of SPA is the use and abuse of client side. I read a lot of experiences from different companies about whether worth to create SPA or to render at server side. The experience from Twitter says a lot. Anyway, thinking in a mixed SPA/Server side takes me too much time in order to get the best trade-off, so I finally decided to migrate as fast as possible, trying to integrate on server side once we detected a bottleneck.

I hope to update this article, or create a new one with my progress on this field.

Greetings!

comments powered by Disqus