Wednesday, March 25, 2020

Implementing CI/CD DevOps pipelines using a simple ASP.NET Core 3.1 MVC application with GitHub Actions and Azure App Services


In this post I will show you how easy it is to implement a CI/CD DevOps pipeline using GitHb Actions. The sample web application I will use is an ASP.NET Core 3.1 MVC application and I will deploy it to Azure App Services. 

Before proceeding, It is assumed that you have the following pre-requisites:
- You already have an Azure Account
- You already have a GitHub account
- You have .NET Core 3.1 (or later) installed on your computer
Creating a simple ASP.NET Core 3.1 application
In a working directory, execute the following command from within a terminal window:

dotnet new mvc -o GithubActions2Azure

Change directory to the newly created app:

cd GithubActions2Azure

Add a .gitignore file to the application:

dotnet new gitignore

Let us make the application our own by, perhaps, changing the title of the app and the background color.

1) Add the following CSS to wwwroot/css/site.css


body {   background-color: tomato;}


2) In Views/Home/Index.cshtml, change the main heading from:

<h1 class="display-4">Welcome</h1>

           TO

<h1 class="display-4">Welcome to our MVC Core 3.1 App</h1>

Let us now run the application and see what it looks like. In the terminal window run the following command:

dotnet run

Point your browser to https://localhost:5001. You will see a strangely colored web page that looks like this:


Stop the server by hitting CTRL + C in the terminal window.

Push code to GitHub

We are now ready to push this application to GitGub. Go to GitHub and create a repository. I created a repository named GithubActions2Azure. Copy the commands that are shown on the GitHub page that looks like this:

Back in your application’s terminal window, type the following commands to initialize a git repo, add files to the repo and commit the changes:

git init
git add .
git commit -m "1st commit"

Next, we will push the code to GitHub. Paste the git commands that you copied from GitHub. This is what it looked like for me:

git remote add origin https://github.com/medhatelmasry/GithubActions2Azure.git
git push -u origin master

If you refresh the GitHub page, you will see that the code is in GitHub. It looks like this:

























Azure

The next step is to create a web app in Azure. Login to the Azure portal at https://portal.azure.com/. Click on Create a resource:

Enter “web" in the filter then choose "Web App”:


On the next page, click on the blue Create button:

 

Choose a subscription then create a new Resource Group:


In named my new resource group GithubActions2Azure. Here are all the choices I made:


Click on Create on the next page:


Creation of a new Azure web service takes less than three minutes. When it is completed, a message appears declaring that “Your deployment is complete”. Click on the blue “Go to resource” button:


We need the publish profile. Click on “Get publish profile” to download your publish profile XML file:


Build & Deploy using GitHub Actions
 Back it GitHub, click on the Settings tab of your application’s repo:


Click on Secrets on the left-side:


Click on “Add a new secret”:


Give the secret the name AZURE_WEBAPP_PUBLISH_PROFILE and paste the contents of the publish profile file that you earlier downloaded from the Azure portal for your web app:

 
Click on Actions on the top navigation bar in GitHub:


You will see a multitude of templates for a multitude of technologies and programming languages. We will paste our own template, therefore, click on the “Set up a workflow yourself” link on the right-side:


This will create a .github/Workflows folder in your application. Name the file deploy_to_azure.yml then click on the green “Start commit” button:


Enter a comment and description for the commit then click on the “Commit new file” button:


Go to this site to get an appropriate template for our web app: https://github.com/Azure/webapps-deploy. Scroll down until you find this section then click on dotnet.yml:


Copy the contents of the asp.net-core-webapp-on-azure.yml. Return to the GitHub repo of our application, edit the deploy_to_azure.yml file, and replace the contents by pasting the clipboard. This is what it looks like for me:


On line 18, set the value of AZURE_WEBAPP_NAME to the name of your app. In my case it is GithubActions2Azure.

On line 20, set the value of DOTNET_VERSION with the exact version of .NET Core with which you created your app. You can find out by running the following command in a terminal window:

dotnet --version

In my case, the .NET Core version is 3.1.200.

Click on the green “Start commit” button, give it a title then click on “Commit changes”.

Click on Actions on the top navigation bar:


Click on “Deploy ASP.NET Are all to ..”. If all goes well, there should be a green check mark beside the workflow, which was responsible for building and deploying the app to Azure. Click on “Updated deploy_to_azure.yml”.


Click on “build-and-deploy” on the left-side:


You will be comforted by the fact that all tasks completed successfully:


To make sure all is well, go to the Azure portal and click on the URL of your website:


Our ugly looking tomato-colored website appears:


Note that if you make any changes to your source code and push it to GitHub, it will automatically get deployed to Azure. This is what CI/CD is all about. Let's try that.

CI/CD
In a terminal window at your project folder, do a pull in order to get all the changes we made in GitHub when we added the .yml file:

git pull

In wwwroot/css/site.css, change the background-color to wheat. Let us push our changes to Github with these commands:

git add .
git commit -m "changed background color to wheat"
git push origin master

Back in GitHub, you will find that the deployment is running:


Upon completion it will display a green check mark:

Refresh the website in your browser and you will find that it has changed background color to something nicer:


Thanks for coming this far in my tutorial and I hope you found it useful.

Friday, March 6, 2020

Build an ASP.NET Core 3.1 tag helper that consumes an API RESTful service

Tag Helpers in ASP.NET Core allow you to create your own tags that fulfill a server-side purpose. In this tutorial, I will show you how to create a tag helper <toon> that accesses a Web API service and displays contents in any razor view page.

The Web API service we will consume in this exercise is located at https://api4u.azurewebsites.net/api/people. It delivers the names of cartoon characters and their respective images.

1) To start with, create an ASP.NET Core Web application named TagHelperDemo in a terminal window using this command:

dotnet new mvc -o TagHelperDemo

2) Next, let's create a class that closely matches the nature of the Web API JSON object. Therefore, add the following CartoonCharacter class to a Models folder in your project:
public class Toon {
  public int Id { get; set; }
  public string LastName { get; set; }  
  public string FirstName { get; set; }
  public string Occupation { get; set; }
  public string Gender { get; set; }
  public string PictureUrl { get; set; }
  public int Votes { get; set; }
}
 3) We will need to install the API Client libraries. To that end, execute the following commands from a terminal window
dotnet add package Microsoft.AspNet.WebApi.Client
dotnet add package System.Runtime.Serialization.Xml
This should add the following dependencies to your project.json file:
<PackageReference Include="System.Runtime.Serialization.Xml" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
 4) Add the following tag to the bottom of Views/Home/Home.cshtml:


<toon></toon>

5) Create a folder named TagHelpers and add to it a class file named ToonTag.cs. Have the class inherit from TagHelper and implement the ProcessAsync() method as follows:

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
}


We could have implemented a method Process() instead. However, in our case, it is appropriate to implement ProcessAsync() instead because we are about to make an async call to a remote service.

6) Add the following instance variable to the ToonTag class:

 private string baseUrl = "https://api4u.azurewebsites.net/";

7) Annotate the ToonTag class with the following:

[HtmlTargetElement("toon")]
[HtmlTargetElement(Attributes = "toonie")]


The first annotation defines the tag <toon> and the second defines the “toonie” attribute. This means that we have two different ways to produce the same output on a razor .cshtml view.

8) Add the following method to the ToonTag class:

async Task<List<Toon>> GetToonsAsync() {
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(baseUrl);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    List<Toon> toons = null;
    try {
        // Get all cartoon characters
        HttpResponseMessage response = await client.GetAsync("/api/people");
        if (response.IsSuccessStatusCode) {
            string json = await response.Content.ReadAsStringAsync();
            toons = JsonConvert.DeserializeObject<List<Toon>>(json);
        }
    } catch (Exception e) {
        System.Diagnostics.Debug.WriteLine(e.ToString());
    }
    return toons;
}

The above code makes a request to the Web API service and returns an List<Toon> collection with the results.

9) Add the following code inside the ProcessAsync() method:

List<Toon> toons = await GetToonsAsync();
string html = string.Empty;
html += "<table><tr><th>Name</th><th>Picture</th></tr>";
foreach (var item in toons) {
    html += "<tr>";
    html += "<td>" + item.FirstName + " " + item.LastName + "</td>";
    html += "<td><img src='" + item.PictureUrl + "' style='width: 50px' /></td>";
    html += "</tr>";
}
html += "</table>";
output.Content.SetHtmlContent(html);

The above code creates a table with the collection of toon characters so that it can be displayed wherever the tag helper is used.

11) Register the tag name in the Views/_ViewImports.cshtml file by adding the following to the list of tags that are already there:

@addTagHelper "TagHelperDemo.TagHelpers.ToonTag, TagHelperDemo"

You may need to adjust the above names depending on what you called your app and/or your tag helper class.

11) Compile and run your application. You should see the following output:



If you inspect the table in your browser, you will see the following:




The above is using the tag and not the attribute.

Edit Home.cshtml and comment out “<toon></toon>” and put the following <div> tag with the toonie attribute underneath it:
<div toonie></div>

When you run your application. you should see the same output as before. If you inspect the table you will see the following HTML source:



This proves to us that you can either use tags or attributes with TagHelpers in ASP.NET Core.