Automatically Deploy ASP.NET MVC, ASP.NET Web API, WCF Services or Generall Web Application to IIS

This is a follow up to my previous blog post on ‘Automated Deployments and Automation, in General, is Essential‘.

NO ONE should EVER deploy web applications manually! If you are currently doing this, please use the following script below and start deploying your web application automatically.

This is a PowerShell script, I must say I’m new to PowerShell, but I found it quite easy to learn and work with.

Gist: https://gist.github.com/zulucoda/81cd751f67a8cbba3605#file-create-web-application-in-iis-ps1

<# .SYNOPSIS
create-web-application - Automatic website creation.
.DESCRIPTION
Allows you to create a website and its ApplicationPool.
.NOTES
File Name : create-web-application.ps1
Author : Muzikayise Flynn Buthelezi - muzi@mfbproject.co.za
Copyright : MFBproject mfbproject.co.za
.EXAMPLE
PS D:\>create-web-application.ps1 -SiteName TESTSITE -Port 8080 -Environment PREPROD -Runtime v4.0 -Pipeline Classic
Creates a website named 'TESTSITE-PREPROD', listening on the TCP8080 port, responding to 'http://*' (default value). The associated ApplicationPool 'TESTSITE' running with the identity 'NetworkService' (default value), v4.0 .NET Framework managed runtime and 'Classic' managed pipeline mode.
#>
Param(
[Parameter(Mandatory=$true, HelpMessage="You must provide a display name for the website.")]
$SiteName = "testsite",
$Port = "8080",
#[ValidatePattern("([\w-]+\.)+[\w-]+(/[\w- ;,./?%&=]*)?")]
$HostName = "",
[ValidateSet("PROD", "PREPROD", "INTEG", "QUAL", "DEV")]
$Environment = "PROD",
[ValidateSet("0", "1", "2", "3", "4")]
$Identity = "2",
[ValidateSet("v1.1", "v2.0", "v4.0")]
[string]$Runtime = "v4.0",
[ValidateSet("Classic", "Integrated")]
[string]$Pipeline = "Integrated"
)
 
switch ($Identity)
{
0 {$FullIdentity = "LocalSystem"}
1 {$FullIdentity = "LocalService"}
2 {$FullIdentity = "NetworkService"}
3 {$FullIdentity = "SpecificUser"}
4 {$FullIdentity = "ApplicationPoolIdentity"}
}
 
function main(){
 
Write-Host "deploy web application"
 
if (LoadIIS7Module -eq $true) {
Write-Verbose "Add a New IIS 7.0 Web Site..."
Add-IIS7Website $SiteName $Port $HostName $Environment $Identity $Runtime $Pipeline
} else {
Write-Host "IIS7 WebAdministration Snapin or Module not found."
Write-Host "Please consult the Microsoft documentation for installing the IIS7 PowerShell cmdlets"
}
}
 
function Check-IfWebsiteExists($SiteName, $Environment){
$SiteName += "-$Environment"
if ((Test-Path -path "IIS:\Sites\$SiteName") -ne $false)
{
return $false
}
return $true
}
 
function LoadIIS7Module () {
$ModuleName = "WebAdministration"
$ModuleLoaded = $false
$LoadAsSnapin = $false
if ((Get-Module -ListAvailable |
ForEach-Object {$_.Name}) -contains $ModuleName) {
Import-Module $ModuleName
if ((Get-Module | ForEach-Object {$_.Name}) -contains $ModuleName) {
$ModuleLoaded = $true
} else {
$LoadAsSnapin = $true
}
}
elseif ((Get-Module | ForEach-Object {$_.Name}) -contains $ModuleName) {
$ModuleLoaded = $true
} else {
$LoadAsSnapin = $true
}
if ($LoadAsSnapin) {
if ((Get-PSSnapin -Registered |
ForEach-Object {$_.Name}) -contains $ModuleName) {
Add-PSSnapin $ModuleName
if ((Get-PSSnapin | ForEach-Object {$_.Name}) -contains $ModuleName) {
$ModuleLoaded = $true
}
}
elseif ((Get-PSSnapin | ForEach-Object {$_.Name}) -contains $ModuleName) {
$ModuleLoaded = $true
}
else {
$ModuleLoaded = $false
}
}
return $ModuleLoaded
}
 
function Read-Choice {
Param(
[System.String]$Message,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String[]]$Choices,
[System.Int32]$DefaultChoice = 1,
[System.String]$Title = [string]::Empty
)
[System.Management.Automation.Host.ChoiceDescription[]]$Poss = $Choices | ForEach-Object {
New-Object System.Management.Automation.Host.ChoiceDescription "&$($_)", "Sets $_ as an answer."
}
$Host.UI.PromptForChoice($Title, $Message, $Poss, $DefaultChoice)
}
 
function Select-IPAddress {
[cmdletbinding()]
Param(
[System.String]$ComputerName = 'localhost'
)
$IPs = Get-WmiObject -ComputerName $ComputerName -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" | ForEach-Object {
$_.IPAddress
} | Where-Object {
$_ -match "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
}
 
if($IPs -is [array]){
Write-Host "`nServer $ComputerName uses these IP addresses:"
$IPs | ForEach-Object {$Id = 0} {Write-Host "${Id}: $_" -ForegroundColor Yellow; $Id++}
$IPs[(Read-Choice -Message "`nChoose an IP Address" -Choices (0..($Id - 1)) -DefaultChoice 0)]
}
else{$IPs}
}
 
function Add-IIS7Website($SiteName, $Port, $HostName, $Environment, $Identity, $Runtime, $Pipeline)
{
Write-Host "`n**********************************************************" -ForegroundColor Yellow
Write-Host "*`t`tAutomatic Website Creation" -ForegroundColor Yellow
Write-Host "*" -ForegroundColor Yellow
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Parameters"
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Website Name (-SiteName):`t`t" -nonewline; Write-Host "$SiteName" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Website Port (-Port):`t`t`t" -nonewline; Write-Host "$Port" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Website Hostname (-Hostname):`t`t" -nonewline; Write-Host "$HostName" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Website Environment (-Environment):`t" -nonewline; Write-Host "$Environment" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " AppPool Identity (-Identity):`t`t" -nonewline; Write-Host "$FullIdentity ($Identity)" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Managed Runtime (-Runtime):`t`t" -nonewline; Write-Host "v$Runtime" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow -nonewline; Write-Host " Managed Pipeline Mode (-Pipeline):`t" -nonewline; Write-Host "$Pipeline" -ForegroundColor DarkGreen
Write-Host "*" -ForegroundColor Yellow
Write-Host "**********************************************************" -ForegroundColor Yellow
if ((Check-IfWebsiteExists $SiteName $Environment) -eq $false) {
Write-Host "Website $SiteName already created!" -ForegroundColor Yellow
return $false
}
 
if ($Identity -eq "3") {
$AppPoolUser = Read-Host "`nPlease provide username for the ApplicationPool identity"
$AppPoolPwd = Read-Host "Please provide the password for '$AppPoolUser' user" -AsSecureString
}
 
$ChosenIP = Select-IPAddress
Write-Host "`nThe selected IP address is: $ChosenIP`n" -ForegroundColor DarkGreen
 
$SiteName += "-$Environment"
# Create the website directory
Write-Host "Creating application directory" -ForegroundColor Yellow
$WWWPath = "C:\inetpub\wwwroot"
$SitePath = "$WWWPath" + "\" + "$SiteName"
if (!(Test-Path $SitePath)) {
New-Item -ItemType Directory -Path $SitePath
}
 
# Creates the website logfiles directory
Write-Host "Creating application logfiles directory" -ForegroundColor Yellow
$LogsPath = "C:\inetpub\logs\LogFiles"
$SiteLogsPath = "$LogsPath" + "\" + "$SiteName"
if (!(Test-Path $SiteLogsPath)) {
New-Item -ItemType Directory -Path $SiteLogsPath
}
 
Import-Module "WebAdministration" -ErrorAction Stop
if ($Pipeline -eq "Integrated") {$PipelineMode = "0"} else {$PipelineMode = "1"}
 
# Creates the ApplicationPool
Write-Host "Creating website application pool" -ForegroundColor Yellow
New-WebAppPool –Name $SiteName -Force
Set-ItemProperty ("IIS:\AppPools\" + $SiteName) -Name processModel.identityType -Value $Identity
if ($Identity -eq "3") {
Set-ItemProperty ("IIS:\AppPools\" + $SiteName) -Name processModel.username -Value $AppPoolUser
Set-ItemProperty ("IIS:\AppPools\" + $SiteName) -Name processModel.password -Value $AppPoolPwd
}
Set-ItemProperty ("IIS:\AppPools\" + $SiteName) -Name managedRuntimeVersion -Value $Runtime
Set-ItemProperty ("IIS:\AppPools\" + $SiteName) -Name managedPipelineMode -Value $PipelineMode
 
# Creates the website
Write-Host "Creating website" -ForegroundColor Yellow
New-Website –Name $SiteName -Port $Port –HostHeader $HostName -IPAddress $ChosenIP -PhysicalPath $SitePath -ApplicationPool $SiteName -Force
Set-ItemProperty ("IIS:\Sites\" + $SiteName) -Name logfile.directory -Value $SiteLogsPath
 
Start-WebAppPool -Name $SiteName
Start-WebSite $SiteName
 
Write-Host "Website $SiteName created!" -ForegroundColor DarkGreen
}
 
main

Automated Deployments and Automation in General is Essential

It’s 02:00 in the morning, and I’ve been up for more than 14 hours now. I’m still manually deploying the latest services and application. It’s my first time deploying these services and apps because usually, other team members do it. We finish the deployment at 05:30 in the morning. We are all tired we go home and rest. We come in at around 11:00. There are some issues with various apps and services. We immediately start investigating. Deep into our investigation, we realise that missing steps caused most of the issues during the deployment. It’s simple things like updating the config or restarting the service. Surely there must be an easier way???

There is an easier way, and we all know what the easy way is. It’s automation. As suggested by Pragmatic Programmer book, we must take advantage of automation as much as possible. Yet we are manually deploying code, WHY? In my last team, the excuse was that we don’t have time to create automation scripts. OR Our suite of services and applications are too complicated to be automated. Fair enough, this might be true in the beginning, maybe there is no time to put together automation scripts because we are trying to complete functionality ASAP. So we let it slip. On our first deployment, we deploy everything within an hour; therefore, we convince ourselves that we don’t need automation.

STOP, don’t fall into this trap, you will pay for it later, just like we did at my previous company.

My suggestion is to set time aside for automation, add this as a practice during development, similar to unit testing or CI (Continuous Integration). What I’ve started doing is automating whatever task I repeatedly do. For example, the images throughout my blog have a filter added to them and are the same size. Also, they have been uploaded automatically to my server. I created a script, which does this.

Create a Cross Platform Node Desktop App Using Node-Webkit

NodeJs is impressive, really really amazing. A client of mine was looking to solve a simple business process, and the only requirement was that it has to be a simple desktop application. So I thought I would try a node desktop app, using node-webkit. To demonstrate how awesome node-webkit, I’ve created a simple tutorial.

What is node-webkit?

Node-webkit is an app runtime based on Chromium and node.js. You can write native apps in HTML and JavaScript with node-webkit. It also lets you call Node.js modules directly from the DOM and enables a new way of writing native applications with all Web technologies. It’s created and developed in the Intel Open Source Technology Centre.

Getting Started

We are going to use yeoman (what is yeoman?) to generate a node-webkit project for us. This yeoman node-webkit generator is awesome, bigups to all the contributors.

Prerequisite

I’m using Ubuntu OS, so I had to install node-webkit 64bit binaries, this is just for dev purpose. When you? create a distribution/ When a distribution is created, it is packaged with relevant files.

Install Yeoman (if you don’t have it installed)

$ sudo npm install -g yo

Install node-webkit generator

$ sudo npm install -g generator-node-webkit

now we can use the node-webkit generator to create out test project.

$ yo node-webkit

now following the yeoman generator instructions

  1. app name: TestProject
  2. project description: To demonstrate how awesome node-webkit
  3. download latest: yes
  4. platform to support: Linux64, Apple, Window$

Okay now that everything has configured, open up the folder with your favourite Editor or IDE. I’m using WebStorm.

Using terminal & grunt build a distribution. This will generate a distribution package for linux

TestProject$ grunt Gruntfile.js dist-linux

now run this newly created distribution package, navigate to:
(remember I’ve setup node-webkit on my ubuntu os, therefore using alias ‘nw’ to open up dist package)

TestProject$ nw dist/app.nw/

if everything was configured correctly then, you node-webkit desptop app will open up, the following: MFB Node-webkit Test Project

As you can see, this is a simple HTML page that has an H1 tag with ‘TestProject’ and a p tag with ‘To demonstrate how awesome node-webkit’

So now we can create and/or style our app by changing the CSS, add images or update the HTML. You could also add twitter boostrap, or AngularJs.

For now though, we are going to keep things simple and just edit the HTML, and CSS.

To update CSS, navigate to /TestProject/app/css/main.css

body {    
            background-color: #2F3238;   
            font-size: 17px;   
            line-height: 27px;   
            font-family: 'Open Sans', sans-serif;    
            color: #F8290C; 
   }

Update the HTML, navigate to /TestProject/app/views/index.html
add to header:

< link href="../css/main.css" rel="stylesheet" />

recreate the distribution package and then open it up, now it should look like this:
MFB Node-webkit Test Project

Conclusion

If you’ve always wanted to create a cross platform desktop application, without using C++, Java, or Python, well now you can create a cross platform desktop application using node-webkit. Or if you want to try something new from the usual, my suggestion is give node-webkit a try, it’s really quick to get something and going. My client is currently using the node-webkit app and to Him it’s just another application which works as expected.

What cool node-webkit applications, have you come across or created?

Git Repo

URL Link: https://github.com/zulucoda/node-webkit-test-project

Notes Are Important And Having A Great Note Taking App Is equally Important

It’s important to have notes especially when you need to store settings or just for taking notes on how to perform tasks. For me, I take down notes when learning something new, for example, how to create a new Rails app, those commands are easy to forget, also I have a point of reference.

Tomboy Notes for Ubuntu

Anyway my Notes application is Tomboy. Tomboy is amazing. I’ve been using it for a long time now. I tried switching to Evernote a couple of years back but it just didn’t quite do it for me. Yes, Evernote is superior, probably one of the best out there, but I like my Tomboy, it’s flexible and I feel like I have more freedom with Tomboy Notes.

I have setup a server which Tomboy synchronises all my notes too. There’s an Android app for Tomboy called Tomdroid, which also synchronises with my server.

Anyway whatever notes application you use, as long as you have one.

To Install Tomboy Notes on Ubuntu

  • Open ‘Ubuntu Software Center’
  • Search for ‘Tomboy Notes’
  • Click Install

What note application do you use? I’m keen to find out what other awesome notes applications are out there.

Deploying Rails Web App For Newbies

The first time I deployed my rails app, I deployed with standard Web brick server. In fact I deployed a couple of Rails apps using Web brick. It was only after listening to a podcast from Ruby Rogues I realised I needed to update my applications. During this podcast everyone made fun of Devs who deploy Rails using Web brick. I was so ashamed that I was one those Devs, so I decided to fix the problem.

Why is it not good to use Web Brick server in Production?

Well Web brick is more of a development server thus it is only meant to be used in development environment.

How to resolve this problem?

It’s actually simple, all you need to do is specify an alternative server in your Gemfile under your Prod settings. The server which I’m using is thin
. It’s that’s simple.
If you’re running your rails app in Heroku change your Procfile

Gemfile

group :production do
  gem 'pg'
  gem 'thin'
end

Procfile

  web: bundle exec rails server thin -p $PORT -e $RACK_ENV as

That’s it’s.

Using WebStorm, IntelliJ Or RubyMine IDEs In Ubuntu

Jetbrains are one of the leading companies when it comes to making IDEs especially for cross platform OS. My desktop OS is Ubuntu Linux, these IDEs really shine when using them on Linux or Mac OS. One of my favourite features is that they have the terminal available within the IDEs. This great when you need execute bash scripts, or startup your server etc…

A small minor issue in Ubuntu

One problem is a random bug which causes the IDEs to loose cursor, therefore it seems like your IDEs is frozen but it’s not you still able to perform mouse clicks and select menus but you just can’t type. There’s a bug open for this issue but because it’s difficult to resolve because it occurs randomly. This may seem frustrating but there’s a simple work around for this.

Solution

Executing this script:

 $ ibus restart

I’ve created a simple bash that you may use when you have this problem. You may create a shortcut to the script.

Have you come across any other weird issues regarding and fixes to those issues for Theses IDEs? If you have please do kindly share your experience?

Software Engineering for Self-taught Programmers

This article explains why I think self-taught programmers should (must) learn about software engineering.

I am a self-taught programmer.

I am a self-taught programmer. However, I did computer science in high school. Pascal was the first programming language I learned. After I completed high school, I got a job at a Web Development company. I continued to teach myself various web application development skills from books, internet tutorials, and work experience.

Those who cannot remember the past are condemned to repeat it.

In Barry Boehm’s article “A View of 20th and 21st Century Software Engineering.”

He begins with the following statement, George Santayana’s statement, “Those who cannot remember the past are condemned to repeat it,” is only half true. The past also includes successful histories. If you haven’t been made aware of them, you’re often condemned not to repeat their successes. This statement made me realise the importance of Software Engineering and why I need to learn about Software Engineering.

What is Software Engineering

Software engineering is the application of a systematic, disciplined,
quantifiable approach to the development, operation, and maintenance
of software; that is, the application of engineering to software.

What resources to use to learn about Software Engineering

  • A View of 20th and 21st Century Software Engineering – Barry Boehm
  • Software Engineering Principles and Practices – Hans Van Vliet

Conclusion

At the minimum, my suggestion is to read Barry Boehm’s article “A View of 20th and 21st Century Software Engineering.”  Perhaps you may try to enrol for a Software Engineering course.

Other Resources

My suggestion is to look at the Joburg Centre for Software Engineering (JCSE), an official Centre at Wits University if you are from South Africa. They offer a CPD in Software Engineering.

Joburg Centre for Software Engineering

www.jcse.org.za

Iterative Persistence

For example, we often set goals: I want to be successful, or whatever the goal is. All goals have that final destination, whether it’s getting to the top, or getting that job, that car, or that house.

I’ve noticed that we come up with a plan on how to do this, let’s say for the example the goal is getting into shape and being more healthy.

So we create a plan: Go to the gym every day and start eating healthy food. I’ve noticed that we put so much pressure on ourselves that we end up regressing and never attain our goals.

What are we doing wrong? Why does this happen?

After many years of working on my personal development, I’ve realised that we fail because we focus on the end goal too much when we should be focusing on doing the things that will help us attain the goal.

Many projects have failed in the software because of trying to deliver the entire solution in one big bang. Now you may ask what does software have to do with not attaining our goals? I’m a Software Developer, and I’m currently doing a course in Software Engineering. In this course, there’s an article by Barry Boehm “A View of 20th and 21st Century Software Engineering” in which he takes us through the evolution of Software Engineering by examining, process, approaches, trends, principles, methods, concurrent (agile), sequential process (waterfall), etc.

One of the main problems was (and still is) trying to design and spec all features needed for the software. This process was and still plagued with a lack of knowing the actual goal of the software. The client understands what they want, but translating this into a formal design, usually, items are missed and are discovered later when development has started already. Now that means going into another design session to see how these new pieces would fit, and this would be a back and forth; eventually, this project fails.

As software engineers discovered this problem, some changed the approach to an iterative process where some design is done upfront, key features are selected from a list, and developed in a sprint lets say 2 to 3 weeks. These feature the deployed after the sprint.

So now getting back to goals and why we sometimes don’t attain them. Like software, we need to adapt the plan initially to be more of an iterative procedure.

Conclusion

My conclusion is almost like software engineering we have to treat our goals the same. Set a goal, see the big picture, plan how you will achieve it. Put the big picture aside, focus on doing the steps in your plan, for example, if you want to get into the shape and go to the gym every day. Go gym every day for the next 3 to 4 weeks, don’t worry about how you are doing, and focus on getting to the gym every day. Once you’ve been going to gym every day for 3 to 4 weeks, you find that now your goal of getting into shape would have changed, now it might be; okay great I’m starting to get into shape, but I see that my gym will be more effective if I start eating healthy food. Now you have a new item added to your list, and you may plan accordingly. For example, you’ve also updated your diet to a healthy one every day you go to the gym. You do this for next 3 to 4 weeks later, your eating healthy, gyming every day but now you want to add on something else, well you repeat the iterative process.

I think you will have more success with this iterative approach than if you bundled up all the things you want into one significant goal example, this year: I want to get into shape, and I want to eat healthy food.