Picking Up SCSS

sass-web-compiler-visual-studio-pluralsight

Last week, during our work discussion, we came to this point where we argued if “fast first, slow later” or “slow first, fast later” is suitable in our working environment.

In startup mode, everything comes at you quickly, and you tend to react fast. So in the first two years of setting up the Innovation Team in Changi Airport, our software development team had been working very hard and very fast to meet the deadline. Now, our company is switching from startup mode to scale-up mode where we need to shift towards doing things right more often than doing things fast.

Hence, we are working on setting up a set of suitable development and design principles in our development team. Applying SCSS to refactor our CSS is part of this time-consuming, difficult, and tiring process.

Installing Web Debugger in VS2015

After the introduce of Web Essentials 2015, features such as compiling SCSS files have been moved to another extension called Web Compiler in Visual Studio.

Hence, to get started in VS2015, we need to first download Web Compiler via Tools > Extensions and Updates.

Installing Extensions in VS2015.png
Installed Web Compiler in Visual Studio 2015

We will need to restart Visual Studio after the installation. Once the Visual Studio is restarted, we then can start using SCSS in our web projects.

By using Web Compiler, every time we save the .scss file, it will auto compile it to be a corresponding .css file (with minified version as well!).

Another feature that I like in this extension is that Visual Studio will specify whether the SCSS files are “Compiled successfully” or there is any SCSS error, as shown in the screenshot below.

SCSS Error Reporting in VS2015.png
Visual Studio will provide friendly error messages for SCSS too!

Refactor CSS into SCSS

Previously, besides using CSS from Bootstrap, we mostly handcrafted our CSS. Recently, it had become quite hard to maintain. So I started to refactor the CSS files from one of our web projects into SCSS.

Firstly, I created a new set of blank SCSS files while keeping the existing CSS files untouched. Secondly, I change the CSS reference of the website to use the new CSS files generated by the Sass pre-compiler. By doing this, I can choose to slowly refactor the existing CSS.

Change I Love #1: Introduction of Variables

Taking just brand colour as an example, currently our CSS files have it all over the place. The same shade of blue appears a lot of times. It is incredibly hard and time consuming to make changes in our web projects using plain CSS.

Previously, for example, we have the following CSS.

.btn-main {
    background-color: #28c8f0;
    border-color: #28c8f0;
}

The primary colour #28c8f0 is used in other classes throughout the whole CSS. Hence, we can just define it as a variable $primary-color: #28c8f0; and then use it

.btn-main {
    background-color: $primary-color;
    border-color: $primary-color;
}

In the future, if we want to change the primary colour to another colour, we just need to change it at one place without worrying if we miss out any part of the CSS not updated.

Change I Love #2: DRY with Mixin

Don’t Repeat Yourself (DRY), if we are using plain CSS, we normally find ourselves reusing the same set of codes throughout the CSS files. So, by using mixins in SCSS, there will always be one and only one set we need to remember and reuse.

Before using SCSS:

.customized-width-250 {
    margin-top: 4px;
    border: 1px solid #ffffff;
    border-radius: 5px 5px 5px 5px;
    font-weight: bold;
    height: 30px;
    min-width: 250px; 
}

.customized-width-120 {
    margin-top: 4px;
    border: 1px solid #ffffff;
    border-radius: 5px 5px 5px 5px;
    font-weight: bold;
    height: 30px;
    min-width: 120px; 
}

.customized-width-60 {
    margin-top: 4px;
    border: 1px solid #ffffff;
    border-radius: 5px 5px 5px 5px;
    font-weight: bold;
    height: 30px;
    min-width: 60px; 
}

Now, by using mixin, we can easily remove the duplicates for easy maintenance.

@mixin customized-controls ($width) {
    margin-top: 4px; 
    border: 1px solid #ffffff; 
    border-radius: 5px 5px 5px 5px; 
    font-weight: bold; 
    height: 30px;
    min-width: $width;
}

.customized-width-250 {
    @include customized-controls(250px);
}

.customized-width-120 {
    @include customized-controls(120px);
}

.customized-width-60 {
    @include customized-controls(60px);
}

Change I Love #3: Loops and Conditional

On our website, we need to display representative image for each of the countries available on the portal.

If we are using plain CSS, we need to do the following for each country. For example, for Australia, we have the follows.

.country-box-australia {
    background-image: url("/images/device-country-australia.png");
}

Now we have 9 countries on our portal. So we need to repeat the lines above for 9 times. If the images are moved to another folder, then we need to update the CSS at 9 places.

In SCSS, we can use list and each loop to make the CSS more readable.

$portal-countries: australia, france, hong-kong, japan, malaysia, new-zealand, south-korea, taiwan, thailand;

@each $country in $portal-countries {
    .country-box-#{$country} {
        background-image: url('/images/device-country-#{$country}.png')
    }
}

As you see above, it also makes use of Interpolation #{} to make the code even cleaner.

Change I Love #4: Color Functions

This is helpful especially when we do the hover effect for buttons. Previously, we always needed to ask the Design Team to give us two colour codes for buttons. One for non-hover and one for hover.

So with the Color Functions in SCSS, we can now do as follows.

a {
    text-decoration: none;
    color: $primary-color;

    &:hover, &:focus {
        text-decoration: none;
        color: darken($primary-color, 20%);
    }
}

We then can have a consistent look-and-feel throughout the whole website.

Oh ya, the & character above is used to reference parent selector.

Change I Love #5: Partials

We can also have partials by starting the name of the partials with an underscore.

Because of partials, we can organize our SCSS files properly according to their functionality.

Conclusion

I believe that now given the fact that our company is already in a scale-up mode, if we keep doing everything in a hacking way, we will easily end up with technical debt soon. Having technical debt means that we will need to spend extra development work in the future because the best overall solution is not implemented in the beginning.

That is why I always welcome opportunities to learn and improve my skills. This includes learning from my teammates via our countless conversations because the conversations kept me inspired and kept me going. The team had made me a better developer. Picking up SCSS is one of the examples and it is only the beginning.

Learning Materials

Advertisements

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.

Journey to ASP .NET MVC 5

When I first worked as web developer after graduation, I used to think what I knew about web development was already enough. However, as I learned more from friends and colleagues, I realized how difficult the field is, even though in Easibook.com we were just dealing with ASP .NET for web development.

New Ideas

Singapore .NET Developers Community meetup
Singapore .NET Developers Community meetup (Photo Credit: .NET Developers Singapore)

I participated in the Singapore .NET Developers Community meetup with my colleagues on 28 January. The theme is about web development. We had the chance to learn about ASP .NET MVC 5, Dependency Injection and how ASP .NET MVC 5 works with Angular JS.

What interested me is the ASP .NET MVC 5 talk given by Nguyen Quy Hy. In work, I was always using ASP .NET Web Forms. When I first started the ASP .NET MVC project in Visual Studio, I was already shocked by new terminologies like Razor, Identity, Scaffold, and all sort of folders, such as Models, Views, Controllers, App_Start, etc. Those are basically not found in my existing Web Forms project.

Working in a startup, there is always more to do and even more to learn, no matter the size of business. In many ways, my job changes frequently. I have to always take time to learn and challenge myself to play with new technology. Hence, learning ASP .NET MVC becomes my new challenge in this year.

I thus decided to write this post to share about what I’ve learned in my ASP .NET MVC 4/5 projects in February.

Bootstrap

Let’s start with simple stuff first. The GUI.

It’s nowadays quite common that people want a website which is responsive and mobile friendly. Luckily, there are frameworks to help. A even better news is that Visual Studio web application template by default is using Bootstrap, a framework providing design and theming features.

Previously we were using VS 2008. There was no such thing as bootstrap in our Web Forms application. Hence, I only started playing with Bootstrap when I did my first ASP .NET MVC 4 project in VS 2012.

ASP .NET web server controls can no longer be seen in ASP .NET MVC project. I was once asked about how GridView and paging were going to be handled in ASP .NET MVC without the use of the web server controls. I found some online discussions and articles which gave good answer to the question.

  1. Grid Controls for ASP .NET MVC
  2. Bootwatch: Free themes for Bootstrap including table and paging themes
  3. Paging, Searching, and Sorting in ASP .NET MVC 5
  4. ASP .NET MVC Paging Done Perfectly with @Html.PagedListPager()

12-Column Grid System is another thing I learnt when playing with Bootstrap. The grid system allows us to easily create complex grid layouts for different devices.

Grid System of Bootstrap 3
Grid System of Bootstrap 3

With the help of Bootstrap, even before I do anything, my web application is already responsive and mobile friendly. It’s true that technology is just a tool but with the right tools, we are able to work more efficiently and productively. =)

Native Support of Clean URL: Good News for SEO

My colleague, who was doing SEO, always received requests to do URL Rewrite in our existing Web Forms applications. Whenever there is a new page created, he has to add a new rule to web.config, sometimes just to get rid of the .aspx thingy.

<urlrewritingnet rewriteOnlyVirtualUrls="true" contextItemsPrefix="QueryString" defaultPage="default.aspx" xmlns="http://www.urlrewriting.net/schemas/config/2006/07">
    <rewrites>
        <add name="RedirectInDomain" virtualUrl="^http\://(.*)/SomethingFriendly"
            rewriteUrlParameter="IncludeQueryStringForRewrite" 
            destinationUrl="~/test.aspx" ignoreCase="true" 
            redirectMode="Permanent" rewrite="Domain" />
        ...
 
     </rewrites>
 </urlrewritingnet>

If there are one thousand pages, then there will be same amount of rules. So in the end, we even need to create separate config file just to keep the rules for URL rewrite.

In ASP .NET MVC 5, with the help of ASP .NET Routing, URLs no need to be mapped to specific web pages. Hence, in MVC web application, we can always see clean URLs which is friendly to not only the web crawler but also sometimes to the users. This is one of the features that I love in ASP .NET MVC.

Identity and Social Network Login

Whenever I visit an online store, I always find it more customer-friendly to accept Facebook or Google login.

Fortunately, ASP .NET Identity is powerful enough to not just accept application-wise user name and password, but also allows the connections from social websites like Facebook, Twitter, and Google+.

I only need to create a Facebook app and then key in the https URL of my website. After that, I put both the application ID and secret key to Startup.Auth.cs. Tada, users can now login to my website with their Facebook credentials.

app.UseFacebookAuthentication(
    appId: "<Facebook app ID here>",
    appSecret: "<Facebook app secret here>");
Localhost HTTPS URL is also accepted! =)
Localhost HTTPS URL is also accepted! =)

Just in case if you also encounter exception saying “Object reference not set to an instance of an object” on the line with AuthenticationManager.GetExternalLoginInfoAsync(), as shown in the following screenshot, please update Microsoft.Owin.Security.Facebook Nuget package.

Facebook Login Exception. Boom!
Facebook Login Exception. Boom!
Update nuget.org - Microsoft.Owin.Security.Facebook
Update nuget.org – Microsoft.Owin.Security.Facebook

Entity Framework Code First

Due to the fact that my project is a new one. So, I used Code First to help me create tables in a new database according to my Model definition.

There is also a video on MSDN Data Developer Center website where they give an introduction to Code First development.

I like how easy it is to have all my tables created auto-magically by just defining model using classes. Then after that, I can create new views and controller by adding Scaffold.

Easily create MVC controller and views with Scafolding
Easily create MVC controller and views with Scafolding

Headache with Migrations

In order to have database scheme updated when the model is changed, I have enabled migration by running the Enable-Migrations command.

Ran Enable-Migrations command in the Package Manager Console
Ran Enable-Migrations command in the Package Manager Console

After that, whenever I changed my model classes, I will run Update-Database to have database schema updated as well. However, soon I encountered a problem.

When I was working on an ASP .NET MVC 4 project with VS2012, the Id in the Users table is integer. So, in VS2013, I assumed it to be the same when I created the model classes and updated the database. Unfortunately, nope. The default web application of VS2013 uses GUID for user ID. There is an online tutorial on how to change the primary key of Users back to integer, if you are interested.

Due to the fact that my project is a totally new project, so what I am going to do is just to change my model classes to use GUID as the type of storing user ID in other tables. However, when I ran the Update-Database command, the console prompted me an error message, saying “Operand type clash: int is incompatible with uniqueidentifier”. To quickly get rid of this problem, I deleted my tables (Don’t do this at home. =P) from the database. Then when I ran Update-Database command again, it complaint the table was missing. Finally, I had no choice but deleting the relevant records in __MigrationHistory table before making Update-Database to work again. =P

Yay, successfully updated database schema after deleting migration history.
Yay, successfully updated database schema after deleting migration history.

Yay with Entity Framework

Before using Entity Framework, I played with stored procedure for few years. My colleagues have always been complaining that sometimes the logic was being hidden in stored procedures and thus made the debugging difficult. Also, having logic in stored procedures means that our business logic is actually split up into both C# and SQL. So, sometimes the developers need to spend a few hours debugging the C# code before realizing the store procedure was actually the culprit.

With Entity Framework, I am now able to modify the table structure and logic all in C# code which helps developers to easily find out where goes wrong.

Still, sometimes it is good to group related functions into one well-defined stored procedure so that the system only needs to call to the database once to get all the work done. However, after reading a 400-line store procedure once, I decided that doing this may not be the best option because no one in my team was interested to debug SQL code.

Review a long stored procedure?
Review a long stored procedure?

There are more related topics online regarding Entity Framework vs. Stored Procedures, as listed below. If you are interested, feel free to check them out.

  1. Entity Framework Vs Stored Procedures – Performance Measure
  2. Stored Procedure or Entities?

Using MySQL Instead of Default SQL Server: I Was Having a Hard Time

By default, the data provider of ASP .NET Identity with Entity Framework is set to be MS SQL in VS 2013. However, MS SQL Server is not free. So, I decided to use MySQL instead. Hence, I need to find ways to configure Entity Framework on my project to work with MySQL.

The first tutorial that I started with is a detailed step-by-step guide on ASP .NET website regarding how to use use MySQL Storage with an Entity Framework MySQL Provider. It mainly involves steps on changing the web.config. Some important steps are listed below.

Change database connection string.

<add name="DefaultConnection" connectionString="Server=localhost;Uid=root;Pwd=password;Database=mediablog;" providerName="MySql.Data.MySqlClient" />

Configure Entity Framework to use MySQL.

<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </providers>
</entityFramework>
<system.data>
    <DbProviderFactories>
        <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.8.3.0" />
    </DbProviderFactories>
</system.data>

However, if I am not wrong, part of these can be done easily by just including the related MySQL nuget packages. I chose four of them to be installed in my project: MySQL.Data, MySQL.Data.Entity, MySQL,Data.Entities, and MySQL.Web.

Install related NuGet packages to make Entity Framework Code First works with MySQL.
Install related NuGet packages to make Entity Framework Code First works with MySQL.

After changing web.config, I followed the tutorial to introduce two new classes in the project. One is MySqlHistoryContext.cs which will sync the model changes with the database schema using MySQL standard and not MS SQL.

According to an online post, I added extra one line to the OnModelCreating method MySQLHistoryContext.cs. It’s to fix the exception of the famous Error 0040: The Type nvarchar(max) is not qualified with a namespace or alias. Only primitive types can be used without qualification.

modelBuilder.Properties<String>().Configure(c => c.HasColumnType("longtext"));

However, the Error 0040 didn’t disappear because of this line. I will share later the other steps I took to fix this problem.

The famous Error 0040 encountered when doing migrations for MySQL.
The famous Error 0040 encountered when doing migrations for MySQL.

Another new class is called MySqlConfiguration which is used to make sure the Entity Framework will use MySqlHistoryContext, instead of the default one.

Besides, I also made changes to Configuration.cs. Remember the Error 0040? A discussion thread on Github actually suggested to add the following line to fix it.

SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());

This didn’t fix the Error 0040 on my project too.

In the end, I found a Chinese post which said the following.

此时只需要将Data层的Migrations的文件夹删掉即可。因为SqlServer做过一些迁移,有些数据类型与MySql不兼容。

The sentence basically says that due to the fact that the migration earlier done in SQL Server and thus some data types are not compatible with MySQL, we need to delete the Migrations folder. So, after I excluded the 201502231459263_InitialCreate.cs file (which was created when I am still using MS SQL for my project) in Migrations folder from the project, the Error 0040 was gone when I did Update-Database. Yay!

So yup, sometimes it’s very, very useful to know more than one language. And yup, I spent half of my holiday to figure out how to make Entity Framework to work with MySQL. =)

Oh well, half day gone just to make MySQL work in my little project.
Oh well, half day gone just to make MySQL work in my little project.

By the way, the Chinese web page mentioned above was already not available. What I shared with you is actually a link to its Google cached copy. I am not sure if the cache is still around when you visit it.

Self Learning ASP .NET MVC on MVA during Chinese New Year

The talks given during the community meetup are good. However, in order to learn more, I also need to get advice from my colleagues who have more experience with ASP .NET MVC.

In addition, during Chinese New Year period, instead of watching the new year shows, I stayed in front of my computer to complete the introductory series of ASP .NET MVC delivered by two Microsoft experts, Christopher Harrison and Jon Galloway. It’s definitely a good starting point for beginners. And yup, the two speakers are very good at explaining the key concepts and they also tell good jokes so you shouldn’t find the course to be boring. =P

Yup, people from Malaysia are watching the live too!
Yup, people from Malaysia are watching the live too!

The End of the Beginning

I am now still a beginner in ASP .NET MVC. I always find that there are many new things to learn in just web development. Actually, it’s very challenging. For example, to get Entity Framework Code First to work with MySQL already takes me half day to figure it out.

Anyway, this is just a post sharing how I get started on ASP .NET MVC. In the future, I will do my best to share with you all more about what I learn in this cool technology. =)

Website Exploded After Using VS2012

VS2008 + VS2012

Two years ago, my friend recommended me to try out the latest Visual Studio after he found out that I was still using VS2008. Recently, I finally decided to switch to use VS2012 while the latest version is already VS2013. Oh well, never mind. However, there was a strange error when I first published my ASP.NET website from VS2012 to the server. Part of the error message is shown below.

Server Error in '/' Application.
Client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'.
 The request failed with the error message:
--
<html>
 <head>
 <title>Configuration Error</title>
 <style>
 body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
 p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
 b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
 H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
 H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
 pre {font-family:"Lucida Console";font-size: .9em}
 .marker {font-weight: bold; color: black;text-decoration: none;}
 .version {color: gray;}
 .error {margin-bottom: 10px;}
 .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
 </style>
 </head>
<body bgcolor="white">
<span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>
<h2> <i>Configuration Error</i> </h2></span>
<font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">
<b> Description: </b>An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
 <br><br>
<b> Parser Error Message: </b>It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.<br><br>
...

It turns out that I already did something wrong in the beginning of migration from older version of Visual Studio to VS2012. Normally, for projects created in older version of Visual Studio, they will need to go through some modifications before they can be opened in VS2012. So, there is a one-way upgrade performed when the project is opened in VS2012 for the first time.

There is a need to upgrade the project when it's created in older VS but is now opened in new VS.
There is a need to upgrade the project when it’s created in older VS but is now opened in new VS.

After the upgrade is done, a migration report will be available. In addition, there will be a Backup folder created in the solution directory. Visual Studio is so nice that it automatically creates a Backup folder storing the copy of the project before the one-way upgrade. However, this also creates a problem because inside the folder, there is a web.config file. So now there will be two web.config files in the solution directory. The error suggests that the code was expecting a virtual directory with only one web.config to be setup on IIS. Thus, having two web.config files in the same directory will cause the error mentioned above to happen.

So, the solution? Just move the Backup folder to somewhere else.

Sometimes, this solution may not be working for your case if you happen to encounter the same error. Hence, I’d like to share with you some other solutions which may help you.

Solution #2: Modify .csproj/.vsproj File

This solution is provided by Microsoft team on Visual Studio feedback page. They claimed that it’s a bug and it would be fixed in the future release of “ASP.NET Web Framework and Tools”.

Solution #3: Create Application on IIS

It turns out that if IIS application is not created, the same error will occur. We need to click on the “Create” button if we notice the “Application Name” is greyed out.

Solution #4: Clean the Project

There is a need to clean the solution before the build. There is a simple 3 steps to follow to do this, as suggested by Johnny Reilly on Stack Overflow.

  1. Clean solution when the solution is configured in Release mode;
  2. Clean solution whilst the solution is configured in Debug mode;
  3. Build the solution in Debug mode.

These are what I have found online so far. If you happen to find a solution that works for this issue, please post it as a comment here. Thank you!