Azure Cloud Service: Say Hi to PaaS

“Let’s move our web applications to cloud.”

It’s quite scary when managers suddenly said something like that. I migrated several web applications which were previously hosted on-premise to Microsoft Azure previously. In order to have least number of codes to change, we chose to use Azure IaaS Virtual Machines (VMs).

From IaaS to PaaS

Creating and managing VMs, however, requires skills and a lot of efforts. I shared my story in Azure Community Singapore meetup previously regarding how our developers sacrificed our sleeping time and weekends just to handle those cloud hosting tasks. Hence, I am now looking for a solution that our developers can just focus on development, not system administration work. That’s when I start to learn more about Azure Cloud Service, the PaaS solution from Azure.

IaaS vs. PaaS
IaaS vs. PaaS

With PaaS, Azure handles most of the system administration work for us. One thing to take note is that even though the applications are still running in VMs, Cloud Service is PaaS, not IaaS. Hence, the developers can simply focus on the deployment of the applications. The platform management will be handled by Azure.

Using PaaS does sound easy. However, unlike IaaS, we need to modify our codes to turn the project into a scalable Azure Cloud Service project that runs on Azure. Also, the disks used in PaaS VMs are no longer persistent. So storage needs to be handled differently.

If you would like to find out more about IaaS and PaaS, please read the Microsoft Azure Documentation about compute hosting options. You will find out one more interesting hosting option available in PaaS called Website (renamed to Web App Service in 2015).

Slots: Production and Staging

When Windows Azure was first announced in Singapore in 2009, I was still studying in NUS School of Computing. I thus had the opportunity to join the Azure student workshop to learn about this cool technology. At that time, publishing a web application to Azure PaaS took about 20 to 30 minutes.

Windows Azure Platform
Windows Azure Platform back in 2009

Today, the deployment speed has been shortened to around 6-10 minutes. The interface of Azure Management Portal has been greatly improved as well. Luckily, some good features, especially the Production and Staging Slots, are still around.

Production and Staging Slots are interesting feature in Azure PaaS. There is no such capability in IaaS because in IaaS, the slot will always be production.

Hence, in IaaS, if we want to upload a new version of codes, normally first we will just go to the live server and then replace the existing applications with the updated version. That normally will make the live web applications go down for a few minutes. This is because the affected websites in IIS may be restarted. In addition, when there is a need to rollback the latest upload on live server, there will be cause troubles for developers too.

In PaaS, we have two slots, Production and Staging. Both of them are given different Virtual IP. The new updates of our code can thus be deployed on the Staging Slot first. Once tested successfully, we simply perform a Virtual IP Swap. The staging environment takes over the VIP of the production environment and then the current production environment takes the staging VIP to become staging environment. The swap happens quickly because the only thing changed is the VIPs. What if we want to rollback the latest upload? Just swap again!

Zero-Downtime Deployment: Slot Swap

The Slot Swap is so interesting that I would like to demo it here.

When we publish the web application to Azure through Visual Studio, we can choose whether to publish it directly to Production Slot or just Staging Slot.

Choose to publish to Production or Staging environment.
Choose to publish to Production or Staging environment.

After the code is successfully deployed to Staging Slot, an URL having GUID string will be created and shown in Microsoft Azure Activity Log window in Visual Studio. Click on the link to visit our web application deployed on Staging Slot.

After tested the web application successfully, we can now swap it with Production Slot.

Let's swap Production and Staging Slots!
Let’s swap Production and Staging Slots!

When I did a swap, the entire process took less than 1 minute to complete. This is very impressive.

Is There a Way to Use Different AppSetting and ConnectionString Based on Production or Staging Environment?

When I first started with Azure Cloud Service, I always thought the “Staging Slot” is meant for testing environment. However, later it turns out that the real purpose of having Production and Staging Slots is to achieve zero-downtime deployment. Hence, the word “staging” should be renamed to something like “Pre-Production”.

Hence, it’s clear that we should not change our web.config based on the environment. This is simply because Staging Slot is not designed for testing environment. So, for testing environment, we should not use the Staging Slot. Instead, we have to setup another Azure Cloud Service for testing purpose.

Many people have been discussing this issue on Stack Overflow.

For me, I will still use the Staging environment for QA. However, to do this, I have to re-configure the web.config in staging before and after VIP swapping. After a swap, I need to publish again the project to staging with testing configuration.

However, if you really, really want to use Staging for QA, please read a code sample which will tell which slot your instance is in. I haven’t tried it yet but it does look promising.

SlotStickyAppSettingNames

For those who are familiar with Azure PowerShell commands, there are actually two commands to make app settings and connection strings not to be swapped together with the slots.

For app settings, we have the following command.

Set-AzureWebsite -Name mywebsite - SlotStickyAppSettingNames @("setting1", "setting2")

For connection string, we use the following command.

Set-AzureWebsite -Name mywebsite -SlotStickyConnectionStringNames @("conn1", "conn2")

In fact, these commands had been recently made available in the new Azure Preview Portal. You just need to choose one of your Azure Web Apps, go to its “Settings” page and then click on “Application Settings”.

Wait… This is for Azure Web App only! Yes, so we now (May 2015) still have no such convenience solution for Azure Cloud Service.

For Azure Web App only: We can now make App Settings and Connection Strings to be sticky to the slots.
For Azure Web App only: We can now make App Settings and Connection Strings to be sticky to the slots.

Pricing

Cloud Service offers a lower rate as compared to Virtual Machine. Previously, when we were using just A1 instance VM in Standard Tier, we have to pay about USD 67 per month with a disk size of 40GB (in 2015). However, for Cloud Service, we pay only about USD 60 per month and the C drive comes with it is already 224GB (in 2015). Wow!

Even so, we need to keep the cost of hosting application on Azure PaaS low because it’s always challenging to answer manager’s questions like “how come we pay even more to host on cloud?”.

I don't money! (Image Credit: Tari Tari)
I don’t money! (Image Credit: Tari Tari)

In additional, it turns out that Staging slot is not free. Both Production and Staging slots will be charged at the same rate. Hence, it’s better to delete the Staging slot if it’s already not in use.

Another of my way to save money is to setup multiple website projects in one web role. By doing so, I don’t have to setup different instances for different website projects. There are many approaches to achieve the goal of multiple websites in one web role. Currently, I have only tried partitioning a domain by using virtual application.

To add a virtual web application to an existing web role, I right-click my solution in Solution Explorer in Visual Studio. After that, I create a new Web Application project.

Add new virtual web application to an existing web role.
Add new virtual web application to an existing web role.

After that, in the ServiceDefinition.csdef, there should be following lines under the <Sites> element.

<Sites>
    <Site name="Web">
        <VirtualApplication name="admin" physicalDirectory="..\AdminPortal" />
        <Bindings>
            <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
    </Site>
</Sites>

To access the newly added virtual web application, I just need to append the value of the name attribute to the URI of the primary website. For example, if my primary website is http://www.mywebsite.com, then the virtual web application above will be accessed at http://www.mywebsite.com/admin.

Yup, so now we can have multiple websites in one web role even though we are using PaaS.

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

PRG Design Pattern

PRG stands for Post-Redirect-Get, a web development design pattern which targets to avoid duplicate form submissions because of refreshing the web page.

Currently, in most of the modern browsers, when we refresh the web page right after we submit a form in the page, we will receive a confirmation alert box asking if we confirm want to re-submit the same form.

The warning received when pressing F5 right after submitting a form on the page.
The warning received when pressing F5 right after submitting a form on the page.

This can happen in an e-commerce website. If the customer accidentally pressed “Continue” button on the box to proceed, then there may be a duplicate online purchase. The confirmation box is good but it does not remove the risk of form re-submission.

To avoid all these issues, PRG web design pattern is introduced.

PRG design pattern can solve the problem of form re-submission.
PRG design pattern can solve the problem of form re-submission. (Image Credit: Wikipedia)

PRG and ASP .NET Web Form

In ASP .NET Web Form context, instead of returning a web page direct, we will do a Response.Redirect (302 Redirect) to a confirmation page (or redirect back to the original same page) first. So now user can safely refresh the result page without causing the form re-submission.

By using PRG design pattern, we will thus need to store the data somewhere so that the two web pages can communicate. For example, if we want to show the Receipt Order Number generated after the POST in the confirmation page, then we can store the number in Session variable.

PRG and ASP .NET MVC

In ASP .NET MVC, instead of using Response.Redirect, we will be using RedirectToAction. Then we will store the data in TempData for the next page to consume, for example.

Thoughts about PRG

PRG design patter is not good for every case having form submission involved. For example, if we have a report module that user can search by providing start date and end date, then it is fine to have form re-submission with every page refresh.

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

Razor Learning Notes

Razor is still a new markup language to me, after working on ASP .NET Web Form projects for 3 years. I started to learn Razor in the beginning of this year (2015), so I decide to note down what I find interesting in my Razor learning journey and then share it here.

A Powerful HTML Helper Method: EditorFor

When I first started learning Razor, I was confused by EditorFor and TextboxFor. So, what is the difference between both of them?

TextboxFor is easy to understand. It is a helper method is used to render a TextBox on the web page no matter which type of the data is passed to the method.

EditorFor is more powerful than TextboxFor. Besides rendering a TextBox, it can also render other HTML elements based on the type of the data. For example, if the datatype is boolean, it renders a checkbox. If the datatype is calendar, it will render a textbox with calendar popup (which is not so nice looking as compared to the calendar popup created using XDSoft DateTimePicker).

Even though the datatype is specified to be DateTime, EditorFor does not provide a control for time section.
Even though the datatype is specified to be DateTime, EditorFor does not provide a control for time section.

EditorFor Accepts Custom Templates

By default, the EditorFor will create a textbox with calendar popup for data which is DateTime. We can change it to use another look-and-feel by create our own template.

So let’s say we want the EditorFor to render five dropdown boxes for each of the following components in DateTime: Year, Month, Day, Hour, and Minute.

Firstly, I create a file called DropDownDateTime.cshtml file which is in charge of the look-and-feel of the custom template. This file needs to be put under /Views/Shared/EditorTemplates. Also, please take note that the filename must be same as the corresponding data type.

@model MyProject.Models.DropDownDateTime
@{
    List<SelectListItem> years = new List<SelectListItem>();
    int prevYearCount = Model.PreviousYearCount;
    int nextYearCount = Model.NextYearCount;
    for (int i = Model.DateTime.Year - prevYearCount; i <= Model.DateTime.Year + nextYearCount; i++)
    {
        years.Add(new SelectListItem() { 
            Text = i.ToString(), 
            Value = i.ToString(), 
            Selected = (i == Model.DateTime.Year ? true : false) });
    }

    List<SelectListItem> months = new List<SelectListItem>();
    for (int i = 1; i <= 12; i++)
    {
        months.Add(new SelectListItem() {
            Text = i.ToString("00"), 
            Value = i.ToString(), 
            Selected = (i == Model.DateTime.Month ? true : false) });
    }
 
    List<SelectListItem> days = new List<SelectListItem>();
    for (int i = 1; i <= 31; i++)
    {
        days.Add(new SelectListItem() { 
            Text = i.ToString("00"), 
            Value = i.ToString(), 
            Selected = (i == Model.DateTime.Day ? true : false) });
    }

    List<SelectListItem> hours = new List<SelectListItem>();
    for (int i = 0; i < 24; i++)
    {
        hours.Add(new SelectListItem() { 
            Text = i.ToString("00"), 
            Value = i.ToString(), 
            Selected = (i == Model.DateTime.Hour ? true : false) });
    }

    List<SelectListItem> minutes = new List<SelectListItem>();
    for (int i = 0; i < 60; i += 15)
    {
        minutes.Add(new SelectListItem() { 
            Text = i.ToString("00"), 
            Value = i.ToString(), 
            Selected = (i == Model.DateTime.Minute ? true : false) });
    }
}

@Html.DropDownList("years", years)
@Html.DropDownList("months", months)
@Html.DropDownList("days", days) at 
@Html.DropDownList("hours", hours) : 
@Html.DropDownList("minutes", minutes)

So, with the help of this template, whenever I pass in a data which has DropDownDateTime as its type, EditorFor will automatically render the five dropdown lists, as shown in the screenshot below.

Yup, customized look-and-feel for DateTime picker.
Yup, customized look-and-feel for DateTime picker.

Razor and Content

When I am building apps using ASP .NET Web Forms, I often need to add some server codes within the HTML in .aspx file. For example,

<h2>Animes</h2>

<ul>
    <% foreach (var anime in animeCollection) { %>
        <li><%= anime.Name %></li>
    <% } %>
</ul>

In Razor, we do not need to explicitly denote the start and end of the server blocks within our HTML. The Razor parser is smart enough to implicitly identify when a server block ends by looking for HTML tags. Hence, Razor is able to keep the HTML clean, as shown in the sample coe below.

<h2>Animes</h2>

<ul>
    @foreach (var anime in animeCollection) {
        <li>@anime.Name</li>
    }
</ul>

However, there are sometimes where the Razor parser cannot do the job properly, especially when we need to mix Razor and Javascript code. For example, when we are rendering diagram using Google Charts, as shown in the sample below.

@{ int counter = 0; }


    var data = new google.visualization.DataTable();

    data.addColumn('string', 'Sales Date');
    data.addColumn('number', 'Sales');

    data.addRows([
        @foreach (var record in dailySalesSummaryRecords)
        {
            counter++;
            if (counter == dailySalesSummaryRecords.Count())
            {
                @:['@record.Key', @record.TotalSales.ToString("0.00")]
            }
            else
            {
                @:['@record.Key', @record.TotalSales.ToString("0.00")],
            }
        }]
    );
    
    ...

The two lines highlighted above are Razor code within JS. Both of them are actually doing the same thing. Just that one of them has no trailing comma which is to avoid browsers like Internet Explorer 8 to throw errors.

The @: Character Sequence is used to explicitly tell Razor to interpret the following line of content as content. However, @: can only work on single line. So for scenarios with multiple lines of content, we need to do something as follows.

...
@: Line one of content
@: Line two of content
@: Line three of content
...

Alternatively, we can just use <text> Tag to effectively mark the start and end of content.

...
<text>
    Line one of content
    Line two of content
    Line three of content
</text>
...

To read more about @: Character Sequence and <text> Tag, please refer to a detailed blog post about them on ScottGu’s Blog.

Razor Encodes String by Default

Yes, Razor encodes string by default. So what should we do if we want rendering without encoding? Well, we can do something as follows.

@Html.Raw(" alert('Hello World!'); ")

<text> Tag, Html.Raw, and Encoding

There is a very interesting discussion on Stack Overflow about how to correctly doing encoding/decoding in Razor with JavaScript. It starts with a question on how to avoid the apostrophe characters in s.Name to be rendered as ‘.

    $(function () { 
        $('#calendar').fullCalendar({
        header: { left: '', center: 'title', right: 'month,agendaWeek,agendaDay' },
        month: 5,
        year: 2011,
        editable: false,
        events: [
            @foreach (var s in ViewBag.Sessions)
            {
                @:{
                @:title: '@s.Name',
                @:start: new Date(@s.Starts.Year, @s.Starts.Month-1, @s.Starts.Day),
                @:end: new Date(@s.Ends.Year, @s.Ends.Month-1, @s.Ends.Day)
                @:},
            }
        ]});
    });

First of all, we change the code to use <text> because the content is multiple lines. Using @: repeatedly seems a bit strange to me.

<text>
    {
        title: '@s.Name'
        start: new Date(@s.Starts.Year, @s.Starts.Month-1, @s.Starts.Day),
        end: new Date(@s.Ends.Year, @s.Ends.Month-1, @s.Ends.Day)
    }
</text>

Next, we will apply Html.Raw so that apostrophes won’t be encoded as ‘.

<text>
    {
        title: '@Html.Raw(s.Name)'
        start: new Date(@s.Starts.Year, @s.Starts.Month-1, @s.Starts.Day),
        end: new Date(@s.Ends.Year, @s.Ends.Month-1, @s.Ends.Day)
    }
</text>

However, without encoding apostrophes, we may break the JavaScript code with the existence of apostrophes characters, such as

title: 'Jiahao's Birthday'

So, we need to still encode it using JavaScriptStringEncode.

<text>
    {
        title: '@Html.Raw(HttpUtility.JavaScriptStringEncode(s.Name))'
        start: new Date(@s.Starts.Year, @s.Starts.Month-1, @s.Starts.Day),
        end: new Date(@s.Ends.Year, @s.Ends.Month-1, @s.Ends.Day)
    }
</text>

Wait… We don’t want apostrophes to be encoded as ‘ in the first place? Why do we doing encoding now?

This is because JavaScriptStringEncode, a newly introduced method in .NET 4, will encode apostrophes not as &#39 which is something not human-friendly, but it will encode it as \’. So yup, this solve the problem.

JavaScriptStringEncode is a great feature which helps us to handle encoding C# string to a JavaScript string. It is able to escape not only apostrophes, but also double quotes (“), question marks (?), backslash (\), and ampersand (&).

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

Summer 2015 Self-Learning

Summer Self-Learning
It has been about half a year since I started to learn ASP .NET MVC and Entity Framework (EF). In this period of time, I have learnt about not just MVC and EF, but also Azure PaaS, Google Maps API, web application security, cool jQuery plugins, Visual Studio Online, etc.

In the beginning of May, I started to note down useful things I’d learned in my learning journey. Months of bringing together information in this summer has helped me compile my notes about what I’ve learned in the past 6 months. I have currently completed compiling notes for 17 topics that I’ve learnt in this summer.

I listed down the title of the 17 posts below to give you a quick overview about all the 17 topics.

Contents

ASP .NET MVC and Entity Framework

Security

Microsoft Azure

Google APIs

Web Development Tools

Learning After Work

I’m working in Changi Airport. The office working hour is from 8:30am to 6pm. In addition, I am staying quite far from the airport which will take about one hour for me to travel from home to office. Hence, the only time that I can have sufficient time to work on personal projects is weekends.

This summer self-learning project is originally planned to be done by the end of May. Normally, it takes me about one day to finish writing a post. After that, if I find any new materials about the topics, I will then modify the post again. Sometimes, however, I am just too tired and I would not write anything even though it’s weekend. Hence, I end up finishing all the 17 topics three months later.

This summer learning project covers not only what I’ve learnt in my personal projects, but also new skills that I learn in my workplace. I always enjoy having a chat with my colleagues about the new .NET technology, app development, Azure hosting, and other interesting development tools. So yup, these 17 articles combine all the new knowledge I acquire.

I’m also very happy that that I am able to meet developers from both .NET Developers Community Singapore and Azure Community Singapore and share with them what I’ve learnt. That gives me a great opportunity to learn from those experienced .NET developers. =)

Azure Community March Meetup in Microsoft Singapore office.
Azure Community March Meetup in Microsoft Singapore office.

I am not that hardworking to work on personal projects every day. Sometimes, I will visit family and friends. Sometimes, I will travel with friends to overseas. Sometimes, I will play computer games or simply just sleep at home. So ya, this self-learning project takes a longer time to complete. =D

Working on personal projects after work is stressful also. Yup, so here is a music that helps reducing my stress. =)