Modernizr and Progressive Enhancement

Modernizr

Since Visual Studio 2012, we can always find this file called modernizr-(version).js in the default ASP .NET 4.5 MVC template. So, what is Modernizr (can be downloaded from Nuget)?

Modernizr is a JS library which is able to detect HTML5 and CSS features in the user’s browser. During page load, Modernizr will start to test those next-generation features. After that, it will create a JS object which contains the test results. For example, Modernizr.canvas will be true if the browser supports the HTML5 <canvas> element.

Modernizr then adds CSS classes to the <html> tag that tell us which CSS / HTML5 features are supported on the current user’s browser. For example, in my Chrome browser, touch feature is not supported, thus, there is a no-touch class added. The other features like video, audio are all supported.

<html class=" js flexbox flexboxlegacy canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">

With this information, we will then be able to provide alternative look-and-feel for those users who are using older versions of browser instead of telling those users “Best view in version xxx of browser yyy”.

With YepNope.js, we will also be able to tell Modernizr what to test and then what JS/CSS to load if the test passes or fails.

Finally, please remember that Modernizr only provides us information about which features are (not) supported. It won’t magically enable those features for us. We need to write corresponding JS/CSS to provide alternative views when the features are not supported on the browser.

In short, Modernizr is a good tool for designers to implement the idea of Progressive Enhancement.

Graceful Degradation

When I was reading about Progressive Enhancement, I read this term called Graceful Degradation. It basically means the way of using the newest and best web technologies while maintaining support for older browsers.

The famous border-radius feature in CSS3 is supported in modern browsers like IE11, Edge, Chrome, and Firefox but it’s not supported in Internet Explorer 7 and 8. Does this stop us from using border-radius in our website? Nope. This is because for users who are still using IE7/8, they can still use the website in the same way as those who are using modern browsers. Just that those who are using old browsers cannot see the beautiful effect of border-radius.

Different visual effect in IE8 and IE11.
Different visual effect in IE8 and IE11.

So basically the idea of Graceful Degradation is that it starts at ideal user experience level and it decreases depending on browser capability down to a minimum level.

Progressive Enhancement

Progressive Enhancement does in the opposite way as Graceful Degradation. It starts at a board minimum user experience and increases depending on browser capability. For example, when user switches from old browser to modern browser, he/she will be able to experience more advanced functionality that will be automatically enabled on the modern browser. So, Modernizr helps us to achieve this by checking if a certain feature is enabled or not on the current browser.

References

Summer 2015 Self-Learning Project

This article is part of my Self-Learning in this summer. To read the other topics in this project, please click here to visit the project overview page.

Summer Self-Learning Banner

Journey to ASP .NET MVC 5 (Episode 2)

ASP .NET MVC - Google Search - Automapper - Excel - Amazon SES

Previous Episode: https://cuteprogramming.wordpress.com/2015/03/01/journey-to-asp-net-mvc-5/

I first said hi to ASP .NET MVC in the beginning of this year. On 28th January, I attended the .NET Developers Singapore meetup and listened to Nguyen Quy Hy’s talk about ASP .NET MVC. After that, I have been learning ASP .NET MVC and applying this new knowledge in both my work and personal projects.

After 6 months of learning ASP .NET MVC, I decided to again write down some new things that I have learnt so far.

URL in ASP .NET MVC and Google Recommendation

According to Google recommendation on URLs, it’s good to have URLs to be as simple as possible and human-readable. This can be easily done with the default URL mapping in ASP .NET MVC. For example, the following code allows to have human-readable URL such as http://www.example.com/Ticket/Singapore-Airlines.

routes.MapRoute(
    name: "Customized",
    url: "Ticket/{airlineName}",
    defaults: new { controller = "Booking", action = "Details", airlineName = UrlParameter.Optional }
);

In addition, Google also encourages us to use hyphens instead of underscores in our URLs as punctuation to separate the words. However, by default, ASP .NET MVC doesn’t support hyphens. One of the easy solutions is to extend the MvcRouteHandler to automatically replace underscores with hyphens.

public class HyphenatedRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        requestContext.RouteData.Values["controller"] =
        requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");

        requestContext.RouteData.Values["action"] =
        requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
 
        return base.GetHttpHandler(requestContext);
    }
}

Then in the RouteConfig.cs, we will replace the default route map to the following mapping.

routes.Add(
    new Route("{controller}/{action}/{id}",
    new RouteValueDictionary(
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
        new HyphenatedRouteHandler())
);

By doing this, we can name our controllers and actions using underscores and then we set all the hyperlinks and links in sitemap to use hyphens.

There are actually many discussions about this online. I have listed below some of the online discussions that I found to be interesting.

  1. Allow Dashes Within URLs using ASP.NET MVC 4
  2. ASP .NET MVC Support for URL’s with Hyphens
  3. Asp.Net MVC: How Do I Enable Dashes in My URLs?
  4. Automate MVC Routing

MVC-ViewModel

Previously when I was working on WPF projects, I learnt the MVVM design pattern. So, it confused me when there was also a “View Model” in MVC. I thought with the use of View Model in ASP .NET MVC, I would be using MVVM too. It later turns out to be not the case.

In MVC, the View Model is only a class and is still considered part of the M (Model). The reason of having ViewModel is for the V (View) to have a single object to render. With the help of ViewModel, there won’t be too much of UI logic code in the V and thus the job of the V is just to render that single object. Finally, there will also be a cleaner separation of concerns.

Why is ViewModel able to provide the V a single object? This is because ViewModel can shape multiple entities from different data models into a single object.

public class CartViewModel
{
    ...

    public List<CartItems> items { get; set; }
 
    public UserProfile user { get; set; }
}

Besides, what I like about ViewModel is that it contains only fields that are needed in the V. Imagine the following model Song, we need to create a form to edit everything but the lyrics, what should we do?

The Song model.
The Song model.

Wait a minute. Why do we need to care about this? Can’t we just remove the Lyrics field from the edit form? Well, we can. However, generally we do not want to expose domain entities to the V.

If people manage to do a form post directly to your server, then they can add in the Lyrics field themselves and your server will happily accept the new Lyrics value. There will be a bigger problem if we are not talking about Lyrics, but something more critical, for example price, access rights, etc.

You want to control what is being passed into the binder.
You want to control what is being passed into the binder. (Image Credit: Microsoft Virtual Academy)

Please take note that the default model binder in ASP .NET MVC automatically binds all inbound properties.

The first simple solution is to use the bind attribute to indicate which properties to bind.

Edit([Bind(Include = "SongID,Title,Length")] Song song)

I don’t like this approach because it’s just a string. There are many mistakes can happen just because of having typo in a string.

So the second solution that I use often is creating a ViewModel which we can use to define only the fields that are needed in the edit form (V).

Same as M (Model), ViewModel also has validation rules using data annotation or IDataErrorInfo.

AutoMapper

By using ViewModel, we need to having mapping code to map between the view model and the domain model. However, writing mapping code is very troublesome especially when there are many properties involved.

Luckily, there is AutoMapper. AutoMapper performs object-object mapping by transforming an input object of one type into an output object of another type.

Mapper.CreateMap<Location, LocationViewModel>();

AutoMapper has a smart way to map the properties from view model and the domain model. If there is a property called “LocationName” in the domain model, AutoMapper will automatically map to a property with the same name “LocationName” in the view model.

Session, ViewData, ViewBag, and TempData

In my first e-commerce project which is using ASP .NET, Session is widely used. From small things like referral URL to huge cart table, all are stored in Session. Everyone in the team was satisfied with using Session until the day we realized we had to do load balancing.

There is a very interesting discussion on Stack Overflow about the use of Session in ASP .NET web applications. I like how one of them described Session as follows.

Fundamentally, session pollutes HTTP. It makes requests (often containing their own state) dependent on the internal state of the receiving server.

In the e-commerce project, we are using In-Process Session State. That means the session has “affinity” with the server. So in order to use load balancing in Microsoft Azure, we have to use Source IP Affinity to make sure the connections initiated from the same client computer goes to the same Datacenter IP endpoint. However, that will cause an imbalanced distribution of traffic load.

Another problem of using In-Process Session State is that once there is a restart on IIS or the server itself, the session variables stored on the server will be gone. Hence, for every deploy to the server, the customers will be automatically logged out from the e-commerce website.

Then you might wonder why we didn’t store session state in a database. Well, this won’t work because we store inserialisable objects in session variables, such as HtmlTable. Actually, there is another interesting mode for Session State, called StateServer. I will talk more about it in my another post about Azure load balancing.

Source IP Affinity
Source IP Affinity

When I was learning ASP .NET MVC in the beginning, I always found creating view model to be not intuitive. So, I used ViewBag and ViewData a lot. However, this caused headaches for code maintenance. Hence, in the end, I started to use ViewModel in MVC projects to provide better Separation of Concern and easily maintainable code. Nevertheless, I am still using ViewBag and ViewData to provide extra data from controller to view.

So what is ViewData? ViewData is a property allowing data to be passed from a controller to a view using a dynamic-bound dictionary API. In MVC3, a new dynamic property called ViewBag was introduced. ViewBag enables developers to use simpler syntax to do what ViewData can do. For example, instead of writing

ViewData["ErrorMessage"] = "Please enter your name";

, we can now write

 ViewBag.ErrorMessage = "Please enter your name";

.

ViewData and ViewBag help to pass data from a controller to a view. What if we want to pass data from a controller to another controller, i.e. redirection. Both ViewData and ViewBag will contain null values once the controller redirects. However, this is not the case for TempData.

There is one important feature in TempData is that anything stored in it will be discarded after it is accessed in the next request. So, it is useful to pass data from a controller to another controller. Unfortunately, TempData is backed by Session in ASP .NET MVC. So, we need to be careful when to use TempData as well and how it will behave in load balancing servers.

JsonResult

Sometimes, I need to return JSON-formatted content to the response. To do so, I will use JsonResult class, for example

[AllowCrossSiteJson]
public JsonResult GetAllMovies()
{
    Response.CacheControl = "no-cache";
    try
    {
        using (var db = new ApplicationDbContext())
        {
            var availableMovies = db.Movies.Where(m => m.Status).ToList();
            
            return Json(new 
            { 
                success = true, 
                data = availableMovies
            }, 
            JsonRequestBehavior.AllowGet);
        }
    }
    catch (Exception ex)
    {
        return Json(new 
        { 
            success = false, 
            message = ex.Message 
        }, 
        JsonRequestBehavior.AllowGet);
    }
}

There are a few new things here.

(1) [AllowCrossSiteJson]

This is my custom attribute to give access to requests coming from different domains. The following code shows how I define the class.

public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RequestContext.HttpContext.Response.AddHeader(
            "Access-Control-Allow-Origin", "*");
       
        base.OnActionExecuting(filterContext);
    }
}

(2) Response.CacheControl = “no-cache”;

This is to prevent caching to the action. There is a great post on Stack Overflow which provides more alternatives to prevent caching.

(3) return Json()

This is to return an instance of the JsonResult class.

(4) success

If you are calling the GetAllMovies() through AJAX, probably you can do something as follows to check if there is any exception or error thrown.

$.ajax({
    url: '/GetAllMovies',
    success: function(data) {
        // No problem
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        var obj = JSON.parse(jqXHR.responseText);
        alert(obj.error);
    }
});

The error callback above will only be triggered when the server returns non-200 status code. I thus introduced another status field to tell the caller more info, for example an exception raised in C# code or any invalid value being passed to GetAllMovies method through AJAX. Hence, in the AJAX call, we just need to update it to

$.ajax({
    url: '/GetAllMovies',
    success: function(data) {
        if (data.success) {
            // No problem
        } else {
            alert(data.message);
        }
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        var obj = JSON.parse(jqXHR.responseText);
        alert(obj.error);
    }
});

(5) JsonRequestBehavior.AllowGet

To give permission to GET request for GetAllMovies method. This has thing to do with JSON Hijacking which will be discussed in my another post.

ActionResult

Other than JsonResult, there are many other ActionResult classes which represent the result of an action method and their respective helper methods.

Currently, I use the following frequently.

  1. ViewResult and View: Render a view as a web page;
  2. RedirectToRouteResult and RedirectToAction: Redirect to another action (TempData is normally used here);
  3. JsonResult and Json: Explained above;
  4. EmptyResult and null: Allow action method to return null.

Export Report to Excel

Two years ago, I wrote a post about how to export report to Excel in ASP .NET Web Form project. So, how do we export report to Excel in MVC project? There are two ways available.

First one can be done using normal ViewResult, as suggested in a discussion on Stack Overflow.

public ActionResult ExportToExcel()
{
    var sales = new System.Data.DataTable("Sales Report");
    sales.Columns.Add("col1", typeof(int));
    sales.Columns.Add("col2", typeof(string));

    sales.Rows.Add(1, "Sales 1");
    sales.Rows.Add(2, "Sales 2");
    sales.Rows.Add(3, "Sales 3");
    sales.Rows.Add(4, "Sales 4");

    var grid = new GridView();
    grid.DataSource = sales;
    grid.DataBind();

    Response.ClearContent();
    Response.Buffer = true;
    Response.AddHeader("content-disposition", "attachment; filename=Report.xls");
    Response.ContentType = "application/ms-excel";
    Response.Charset = "";
 
    StringWriter sw = new StringWriter();
    HtmlTextWriter htw = new HtmlTextWriter(sw);
    grid.RenderControl(htw);

    Response.Output.Write(sw.ToString());
    Response.Flush();
    Response.End();

    return View("Index");
}

Second way will be using FileResult, as suggested in another discussion thread on Stack Overflow. I simplified the code by removing the styling related codes.

public sealed class ExcelFileResult : FileResult
{
    private DataTable dtReport;

    public ExcelFileResult(DataTable dt) : base("application/ms-excel")
    {
        dtReport = dt;
    }

    protected override void  WriteFile(HttpResponseBase response)
    {
        // Create HtmlTextWriter
        StringWriter sw = new StringWriter();
        HtmlTextWriter tw = new HtmlTextWriter(sw);

        tw.RenderBeginTag(HtmlTextWriterTag.Table);

        // Create Header Row
        tw.RenderBeginTag(HtmlTextWriterTag.Tr);
        DataColumn col = null;
        for (int i = 0; i < dtReport.Columns.Count; i++)
        {
            col = dtReport.Columns[i];
            tw.RenderBeginTag(HtmlTextWriterTag.Th);
            tw.RenderBeginTag(HtmlTextWriterTag.Strong);
            tw.WriteLineNoTabs(col.ColumnName);
            tw.RenderEndTag();
            tw.RenderEndTag();
        }
        tw.RenderEndTag();

        // Create Data Rows
        foreach (DataRow row in dtReport.Rows)
        {
            tw.RenderBeginTag(HtmlTextWriterTag.Tr);
            for (int i = 0; i <= dtReport.Columns.Count - 1; i++)
            {
                tw.RenderBeginTag(HtmlTextWriterTag.Td);
                tw.WriteLineNoTabs(HttpUtility.HtmlEncode(row[i]));
                tw.RenderEndTag();
            }
            tw.RenderEndTag();
        }

        tw.RenderEndTag();

        // Write result to output-stream
        Stream outputStream = response.OutputStream;
        byte[] byteArray = Encoding.Default.GetBytes(sw.ToString());
        response.OutputStream.Write(byteArray, 0, byteArray.GetLength(0));
    }
}

To use the code above, we just need to do the following in our controller.

public ExcelFileResult ExportToExcel()
{
    ...
    ExcelFileResult actionResult = new ExcelFileResult(dtSales) 
    { 
        FileDownloadName = "Report.xls" 
    };

    return actionResult;
}

Sending Email

To send email from my MVC project, I have the following code to help me out. It can accept multiple attachments too. So I also use it to send email with report generated using the code above attached. =)

In the code below, I am using Amazon Simple Email Service (SES) SMTP.

public Task SendEmail(
    string sentTo, string sentCC, string sentBCC,  string subject, string body, 
    string[] attachments = null) 
{
    // Credentials:
    var credentialUserName = "<username provided by Amazon SES>;
    var sentFrom = "no-reply@mydomain.com";
    var pwd = "<password provided by Amazon SES>";

    // Configure the client:
    System.Net.Mail.SmtpClient client = 
        new System.Net.Mail.SmtpClient("email-smtp.us-west-2.amazonaws.com");
    client.Port = 25;
    client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
    client.UseDefaultCredentials = false;

    // Create the credentials:
    System.Net.NetworkCredential credentials = 
        new System.Net.NetworkCredential(credentialUserName, pwd);
    client.EnableSsl = true;
    client.Credentials = credentials;

    // Create the message:
    var mail = new System.Net.Mail.MailMessage(sentFrom, sentTo);
    string[] ccAccounts = sentCC.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
 
    foreach (string ccEmail in additionalCcAccounts)
    {
        mail.CC.Add(ccEmail);
    }
    
    string[] bccAccounts = sentBCC.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

    foreach (string bccEmail in additionalBccAccounts) 
    {
        mail.Bcc.Add(bccEmail); 
    }
    
    mail.Subject = subject;
    mail.Body = body;
    mail.IsBodyHtml = true;

    if (attachments != null) 
    {
        for (int i = 0; i < attachments.Length; i++)
        {
            mail.Attachments.Add(new System.Net.Mail.Attachment(attachments[i]));
        }
    }

    client.SendComplete += (s, e) => client.Dispose();
    return client.SendMailAsync(mail);
}

To send an email without attachment, I just need to do the following in action method.

var emailClient = new Email();
await emailClient.SendEmail(
    "to@mydomain.com", "cc1@mydomain.com;cc2@domain.com", "bcc@mydomain.com", 
    "Email Subject", "Email Body");

To send email with attachment, I will then use the following code.

string[] attachmentPaths = new string[1];

var reportServerPath = Server.MapPath("~/report");

attachmentPaths[0] = reportServerPath + "\\Report.xls";

var emailClient = new Email();
await emailClient.SendEmail(
    "admin@mydomain.com", "", "", 
    "Email Subject", "Email Body", attachmentPaths);

Yup, that’s all what I have learnt so far in my MVC projects. I know this post is very, very long. However, I am still new to MVC and thus I am happy to be able to share with you what I learn in the projects. Please correct me if you find anything wrong in the post. Thanks! =)

Summer 2015 Self-Learning Project

This article is part of my Self-Learning in this summer. To read the other topics in this project, please click here to visit the project overview page.

Summer Self-Learning Banner

Here Comes the Win2D

Win2D - VS2015

I am very fortunate to be able to attend the Singapore .NET Developer meetup of this month. The topics of the meetup are MVVM, Windows 10, and Win2D. We are glad to have experienced developer, Riza, to be one of the speakers.

Riza's sharing his thoughts about Win2D.
Riza’s sharing his thoughts about Win2D. (Image Credit: .NET Developer Singapore Community)

Due to time constraint, Riza only managed to show us some basic codes for Win2D, a WinRT API for Immediate Mode 2D Graphic Rendering with GPU Acceleration.

Immediate Mode and Retained Mode are two main categories in Graphics API. What are they? I always use the following explanations to help me differentiate between the two modes.

Retained Mode does not directly cause actual graphic rendering. Example: WPF.

Immediate Mode will directly cause actual graphic rendering. Example: Direct2D and System.Drawing library.

Last year, Microsoft proudly announced the Win2D which developers could use it to bring hardware accelerated Direct2D graphics to Windows 8.1 Universal Apps. This undoubtedly is a great news for game developers who would like to publish their games on Surface and Windows Phone in the future.

Let’s Start Coding!

I thus decided to read through some online tutorials to try out this new cool API. The following are two tutorials that I read.

  1. Introduction to Win2D
  2. Win2D – WinRT API for 2D Graphics

The first app that I developed is an app similar to what is being shown in the first tutorial listed above.

Pavel’s code doesn’t work well when I am using the latest version of Win2D from Nuget (Version 0.0.20). For example, the way he sets the speed of the moving circle is as follows.

circle.Speed = new Vector2(-circle.Speed.X, circle.Speed.Y);

However, this won’t work in my project. So, I changed it to the code below.

circle.Speed = new Vector2() { X = -circle.Speed.X, Y = circle.Speed.Y };

For those who play with XNA Framework often should know Vector2 quite well. Yup, it is a vector with 2 components, X and Y. In Win2D, besides Vector2, there are also Vector3 and Vector4.

Required Nuget Package

Before doing the coding, there is a need to add Win2D to the Windows 8.1 Universal App project first.

The interface of Nuget Package Manager has changed in VS2015! Here, we can find Win2D package.
The interface of Nuget Package Manager has changed in VS2015! Here, we can find Win2D package.

VS2015 and Azure

As you can see from the screenshot above, it’s actually VS2015 on Microsoft Azure! On Azure, we can easily create a VM with one of the following editions of VS2015 installed: Professional, Enterprise, and Community. Hence, I no longer need to download VS2015 to my own laptop. =)

However, when I first started the VS 2015 on the new VM, I encountered two problems once I tried to compile my Windows 8.1 Universal App.

Firstly, it said developer license couldn’t be approved because of having no Desktop Experience feature enabled.

“We couldn’t get your developer license for Windows Server 2012 R2”

This was easily solved by enabling the Desktop Experience feature. In the beginning, I was having a hard time finding where to enable the Desktop Experience. Thanks to a blog post written by Tamer Sherif Mahmoud, I found the option as shown in the following screenshot.

Desktop Experience option is actually under User Interfaces and Infrastructure.
Desktop Experience option is actually under User Interfaces and Infrastructure.

Secondly, VS2015 complaint that the Windows 8.1 Universal App couldn’t be activated by the Built-in Adminstrator.

“This app can’t be activated by the Built-in Adminstrator”

What I did to fix this problem is only switching on the Admin Approval Mode for the Built-in Administrator account in Local Group Policy Editor, as shown in the screenshot below.

Enable the UAC: Admin Approval Mode for the Built-in Administrator Error - Solution Step 3 - UAC Admin Approval Mode for Built-in Administrator account.
Enable the UAC: Admin Approval Mode for the Built-in Administrator Error – Solution Step 3 – UAC Admin Approval Mode for Built-in Administrator account.

After doing all these, I could finally compile my first Windows 8.1 Universal App in VS2015.

The UI

<Page
 x:Class="MyUniversal.MainPage"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:local="using:MyUniversal"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:win2d="using:Microsoft.Graphics.Canvas.UI.Xaml" 
 mc:Ignorable="d">
    <Grid x:Name="_mainGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <win2d:CanvasControl ClearColor="Black" Grid.Row="1" Draw="OnDraw" x:Name="_canvas" Tapped="OnTapped" />
    </Grid>
</Page>

In order to use CanvasControl, I need to include Microsoft.Graphics.Canvas.UI.Xaml, as highlighted in green in the code above.

The Logic

The following is my Main method.

public MainPage()
{
    this.InitializeComponent();
    _width = (float)Window.Current.Bounds.Width;
    _height = (float)Window.Current.Bounds.Height;
    _timer.Tick += (s, e) => {
        Dictionary<CircleData, int> reference = _circles.ToDictionary(x => x.Key, x => x.Value);

        foreach (var circleKeyPair in reference)
        {
            var circle = circleKeyPair.Key;

            int circleRadiusChangingSpeed = circleKeyPair.Value;

            float posX = circle.Speed.X + circle.Center.X; 
            float posY = circle.Speed.Y + circle.Center.Y;
            circle.Radius += circleRadiusChangingSpeed;

            if (circle.Radius > _height / 4 || circle.Radius <= 0)
            {
                _circles[circle] = -1 * circleKeyPair.Value;
            }

            var radius = circle.Radius;
            if (posX + radius > _width || posX - radius < 0) 
            {
                circle.Speed = new Vector2() { X = -circle.Speed.X, Y = circle.Speed.Y };
            } 
            else if (posY + radius > _height || posY - radius < 0) 
            {
                circle.Speed = new Vector2 { X = circle.Speed.X, Y = -circle.Speed.Y };
            }
            circle.Center = new Vector2 { X = circle.Speed.X + circle.Center.X, Y = circle.Speed.Y + circle.Center.Y };
        }
        
        _canvas.Invalidate();
    };
    
    _timer.Start();
}

In the code, I first define the area to have the circles by declaring two variables _width and _height to be the width and height of the current window. I can’t use the width and height (or even actualWidth and actualHeight) of the grid because they are always 0.

Then same as Pavel, I also move the circles around by having the following code.

circle.Center = new Vector2 { X = circle.Speed.X + circle.Center.X, Y = circle.Speed.Y + circle.Center.Y };

Here, I can’t set X = posX and Y = posY because the circle.Speed here, which is used to define the moving speed and direction, can be already different as the circle.Speed when posX and posY were calculated.

In addition, I also add in the code to change the size of the circle every time it moves. The circle will grow until a certain size and then its radius will be decreased to 0. Once the radius is 0, it will start to increase again.

if (circle.Radius > _height / 4 || circle.Radius <= 0)
{
    _circles[circle] = -1 * circleKeyPair.Value;
}

For those who are wondering what the following line of code does, it is basically just a way to make the canvas control to redraw.

_canvas.Invalidate();

For the OnTapped and OnDraw, I am using the same codes as Pavel’s.

The following screenshot shows the colourful circles created by clicking on the app a few times.

Colourful circles created with DrawCircle.
Colourful circles created with DrawCircle.

That is done using DrawCircle. So, let’s see what will happen if I change to use FillCircle with an image, as taught in the second tutorial mentioned above.

session.FillCircle(circle.Center, circle.Radius, circle.CircleInnerImageBrush);

The CircleInnerImageBrush is created in the following way.

CanvasBitmap image = await CanvasBitmap.LoadAsync(_canvas.Device,
    new Uri("<URL to the image here>"));
CanvasImageBrush imageBrush = new CanvasImageBrush(_canvas.Device, image)
{
     ExtendX = CanvasEdgeBehavior.Clamp,
     ExtendY = CanvasEdgeBehavior.Wrap,
     SourceRectangle = new Rect(0, 0, image.Bounds.Width, image.Bounds.Height)
};

Then I am able to get the following cool effects!

FillCircle + Image
FillCircle + Image

Win2D is Open Source

That’s what I have learnt so far after listening to Riza’s 10-minute sharing on Win2D. I will probably try out the API more in the near future because Win2D looks very promising!

In case, you wonder how much I spent on running VS2015 on Azure, running an A4 (8 cores, 14GB memory) instance for about one week costed me about USD 90.

Oh ya, Win2D is open source! For those who are interested to find out more, please take a look at their GitHub site.

Machine Learning in Microsoft Azure

Let me begin with a video showing how Machine Learning helps to improve our life.

The lift is called ThyssenKrupp Elevator, an example of Predictive Maintenance. For more information about it, please read an article about how the system works and the challenges of implementing it on different types of lift.

I first learnt about the term “Machine Learning” when I was taking the online Stanford AI course in 2011. The course basically taught us about the basics of Artificial Intelligence. So, I got the opportunity to learn about Game Theory, object recognition, robotic car, path planning, machine learning, etc.

We learnt stuff like Machine Leaning, Path Planning, AI in the online Stanford AI course.
We learnt stuff like Machine Leaning, Path Planning, AI in the online Stanford AI course.

Meetup in Microsoft

I was very excited to see the announcement from Azure Community Singapore saying that there would be a Big Data expert to talk about Azure Machine Learning in the community monthly meetup.

Doli was telling us story about Azure Machine Learning.
Doli was telling us story about Azure Machine Learning. (Photo Credit: Azure Community Singapore)

The speaker is Doli, Big Data engineer working in Malaysia iProperty Group. He gave us a good introduction to Azure Machine Learning, and then followed by Market Basket Analysis, Regression, and a recommendation system works on Azure Machine Learning.

I found the talk to be interesting, especially for those who want to know more about Big Data and Machine Learning but still new to them. I will try my best to share with you here what I have learned from Doli’s 2-hour presentation.

Ano… What is Machine Learning?

Could we make the computer to learn and behave more intelligently based on the data? For example, is it possible that from both the flight and weather data, we can know which scheduled flights are going to be delayed? Machine Learning makes it possible. Machine Learning takes historical data and make prediction about future trend.

This Sounds Similar to Data Mining

During the meetup, there was a question raised. What is the difference between Data Mining and Machine Learning?

Data Mining is normally carried out by a person to discover the pattern from a massive, complicated dataset. However, Machine Learning can be done without human guidance to predict based on previous patterns and data.

There is a very insightful discussion on Cross Validated that I recommend for those who want to understand more about Data Mining and Machine Learning.

Supervised vs. Unsupervised Learning

Two types of Machine Learning tasks are highlighted in Doli’s talk. Supervised and unsupervised learning.

Machine Learning - Supervised vs Unsupervised Learning
Machine Learning – Supervised vs Unsupervised Learning

In supervised learning, new data is classified based on the training data which are accompanied with labels to help the system to learn by example. The web app how-old.net which went viral recently is using supervised learning. There is an interesting discussion on Quora about how how-old.net works. In the discussion, the Microsoft Bing Senior Program Manager, Eason Wang, also shared his blog post about this how-old.net project that he works on.

Gmail is also using supervised learning to find out which emails are spam or need to be prioritized. In the slides of Introduction to Apache Mahout, it uses YouTube Recommendation an example of supervised learning. This is because the recommendation given by YouTube has taken videos explicitly liked, added to favourites, rated by the user.

I love watching anime so YouTube recommended me some great anime videos. =P
I love watching anime so YouTube recommended me some great anime videos. =P

Unlike supervised learning, unsupervised learning is trying to find structure in unlabeled data. Clustering, as one of the unsupervised learning techniques, is grouping data into small groups based on similarity such that data in the same group are as similar as possible and data in different groups are as different as possible. An example for unsupervised learning is called the k-means Clustering.

Clearly, the prediction of Machine Learning is not about perfect accuracy.

Azure Machine Learning: Experiment!

With Azure Machine Learning, we are now able to perform cloud-based predictive analysis.

Azure Machine Learning is a service that developer can use to build predictive analytic models with training datasets. Those models then can be deployed for consumption as web service in C#, Python, and R. Hence, the process can be summarized as follows.

  1. Data Collection: Understanding the problem and collecting data
  2. Train: Training the model
  3. Analyze: Validating and tuning the data
  4. Deploy: Exposing the model to be consumed

Data Collection

Collecting data is part of the Experiment stage in Machine Learning. In case some of you wonder where to get large datasets, Doli shared with us a link to a discussion on Quora about where to find those public accessible large datasets.

In fact, there are quite a number of sample datasets available in Azure Machine Learning Studio too. During the presentation, Doli also showed us how to use Reader to connect to a MS SQL server to get data.

Get data either from sample dataset or from reader (database, Azure Blob Storage, data feed reader, etc.)
Get data either from sample dataset or from reader (database, Azure Blob Storage, data feed reader, etc.).

To see the data of the dataset, we can click on the output port at the bottom of the box and then select “Visualize”.

Visualize the dataset.
Visualize the dataset.

After getting the data, we need to do pre-processing, i.e. cleaning up the data. For example, we need to remove rows which have missing data.

In addition, we will choose relevant columns from the dataset (aka features in machine learning) which will help in the prediction. Choosing columns requires a few rounds of experiments before finding a good set of features to use for a predictive model.

Let's clean up the data and select only what we need.
Let’s clean up the data and select only what we need.

Train and Analyze

As mentioned earlier, Machine Learning learns from a dataset and apply it to new data. Hence, in order to evaluate an algorithm in Machine Learning, the data collected will be split into two sets, the Training Set for Machine Learning to train the algorithm and Testing Set for prediction.

Doli said that the more data we use to train the model the better. However, they are many people having different opinions. For example, there is one online discussion about the optimal ratio between the Training Set and Testing Set. Some said 3:2, some said 1:1, and some said 3:1. I don’t know much about Statistical Analysis, so I will just make it 1:1, as shown in the tutorial in Machine Learning Studio.

Randomly split the dataset into two halves: a training set and a testing set.
Randomly split the dataset into two halves: a training set and a testing set.

So, what “algorithm” are we talking about here? In Machine Learning Studio, there are many learning algorithms to choose from. I won’t go into details about which algo to choose here. =)

Choose learning algorithm and specify the prediction target.
Choose learning algorithm and specify the prediction target.

Finally, we just hit the “Run” button located at the command bar to train the model and make a prediction on the test dataset.

After the run is successfully completed, we can view the prediction results.

Visualize results.
Visualize results.

Deploy

From here, we can improve the model by changing the features, properties of algorithm, or even algorithm itself.

When we are satisfied with the model, we can publish it as a web service so that we can directly use it for new data in the future. Alternatively, you can also download an Excel workbook from the Machine Learning Studio which has macro added to compute the predicted values.

Read More and Join Our Meetup!

If you would like to find out more about Azure Machine Learning, there is a detailed step-by-step guide available on Microsoft Azure documentation about how to create an experiment in Machine Learning Studio. There is also a free e-book from Microsoft about Azure Machine Learning. Please take a look!

Oh ya, in case you would like to know more about how-old.net which is using Machine Learning, please visit the homepage of Microsoft Project Oxford to find out more about the Face APIs, Speech APIs, Computer Vision APIs, and other cools APIs that you can use.

Please correct me if you spot any mistake in my post because I am still very, very new to Machine Learning. Please join our meetup too, if you would like to know more about Azure.