Create an Angular 7 / ASP.NET Core 2.2 application and push it to Azure

Create an Angular 7 / ASP.NET Core 2.2 application and push it to Azure

I recently initiated a new Web Application with Angular for the front-end side (JavaScript) and ASP.NET Core for web application hosting and back-end side.

Implementing the full CI/CD cycle was not easy, some digging and experimentation was necessary to make everything work. The goal of this article is to provide an easy (I hope!) procedure to see the different steps and tricks.

The biggest advantage of this technical solution (in comparison to a pure Angular app) is that I can hide and protect calls to particular APIs, either restricted in the IS (internal network) or critical such as the authentication.

Source code is available on GitHub: devpro/aspnetcore-angular-sample.

1. Setup

  • .NET Core 2.2 SDK
    • At the time of writing (3rd of Feb ’19), 2.2 is not installed with the latest version of Visual Studio 2017 (15.9.6), you have to install it manually from dotnet/download. Latest version is Microsoft .NET Core SDK 2.2.103 which installs: .NET Core SDK 2.2.103, .NET Core Runtime 2.2.1 and ASP.NET Core Runtime 2.2.1.
    • You can check the version by running: dotnet -v.
  • NPM
    • NPM comes with the installation of NodeJS
    • You can upgrade the version by running: npm install -g npm (self update is one of my favorite console features) and check the version: npm -v (6.7.0 at the time).
  • Visual Studio 2017 (optional)
    • Version 15.9.6
    • Workloads: “ASP.NET and web development”, “.NET Core cross-platform development”
  • GitHub account or any other git remote repository provider account
  • Azure account
  • Azure DevOps (formerly named VSTS)
  • SonarCloud account (optional), it is free and you can log in with your GitHub account

2. Create the web application

2.1 Initiate a Git repository (source control)

You can chose the provider you want as long as it is accessible from Azure DevOps. Personnally, I would go with GitHub.

Then, you just have to clone this repository locally and create a new feature branch. It is optional to do this before the following but it is how I’m used to work 😀.

2.2 Use Visual Studio template

Open “Visual Studio 2017” and click on “Create new project…”. A small wizard will help you create the first project. You could do this also from the command line with dotnet.

Go in “.NET Core” and select “ASP.NET Core Web Application”, edit the name, location (where you did the git clone) and solution name. Click “OK” to go on the second page, make sure you can see “ASP.NET Core 2.2” at the top of the window, select “Angular” and click on “OK”.

At this point, the project has been created, you can see the file hierarchy in the “Solution Explorer” Window. There are not much but this is why .NET Core is so great (in comparison with the old .NET way), very few files are needed so much easier to work with!

Feel free to have a look at the different files:
ClientApp is where the Angular application is located
Controllers is where you have ASP.NET Controllers, there is a basic Controller here to demonstrate the call from Angular application
– Pages directory and Program.cs file can be ignored, it’s the plumbing between ASP.NET Core and Angular
Startup.cs is important for the configuration of the ASP.NET application (like dependency injection configuration)

2.3 File edition

Some updates need to be made on the source code that has been generated to make everything work.

  • src directory
    • Manually rename the solution folder created by VS 2017 to src, edit and move the .sln (solution) file so that it is at the root folder.
    • Add a .gitattributes file and a .gitignore file at the root to avoid git issues.
    • NB: I don’t like the “autocrlf” option and I prefer to do it per repository. Fighting with line ending is a great battle for Windows developers, a cousin of the “Fun with Encoding” subject…
  • src/WebApp/.gitignore
    • Add the following lines
# Local development settings
/appsettings.Development.json
  • *.csproj files
    • As we’re going to use SonarCloud, mandatory lines must be added to every csproj file of the solution (look at AssemblyName, RootNameSpace, ProjectGuid and the Debug PropertyGroup).
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AssemblyName>Devpro.AspNetCoreAngularSample.WebApp</AssemblyName>
    <RootNamespace>Devpro.AspNetCoreAngularSample.WebApp</RootNamespace>
    <ProjectGuid>{01549AAD-2FF4-4B8B-9B63-7E00C2948E96}</ProjectGuid>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>

    <!-- Set this to true if you enable server-side prerendering -->
    <BuildServerSideRenderer>false</BuildServerSideRenderer>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

2.4 Build

You can build either from Visual Studio or from the command line by running: dotnet build.

It will take several minutes to do the first build as npm will gather the packages from scratch but it will be almost immediate afterwards.

2.5 Run

You can run the web application directly from Visual Studio (with Debug) or easily from the command line by running: dotnet run –project src/WebApp.

The site will be available on localhost:5000. You may have a security alert about certificate and HTTPS, you can deactivate this from Startup.cs if it annoys you.

You can then enjoy very basic Angular POC functionalities by going on the “Counter” and “Fetch data” pages.

2.6 Test

An important part of the CI pipeline is to run the tests and produce the code coverage.

  • To do so, you have to install the following NPM packages: npm install karma-junit-reporter karma-phantomjs-launcher phantomjs-prebuilt –save-dev
  • And, manually edit:
    • package.json to add test-ci target
    • angular.json to add codeCoverageExclude for test
    • src/karma.conf.js to add phantomjs and junit configuration
    • src/polyfills.ts to uncomment es6 lines
  • Then, you can launch the tests locally with: npm test, npm run test-ci

3. Create the Continuous Integration (CI) pipeline

3.1 Create a new SonarCloud project

Go to SonarCloud, click on your Organization, then click on “Administration” and “Projects Management”.

Click on “Create Project” and fill the name and the key. You can then create a token if not done already, this is required from Azure DevOps to create a connection between the two systems.

3.2 Create a new Build Pipeline

You can find the full definition from the public project Demo (you can export the json definition of the pipeline).

Go to “Azure DevOps”, log in, create a new Project (or use an existing one). Then, click “Pipelines” > “Builds” from the menu on the left and click on “New Pipeline”.

There are basically two ways to do it: 1/ yaml file, 2/ visual designer (this is for me the easiest way to learn). Click on the link “Use the visual designer”, select the “source” (git repository), gives an authorization if it’s the first time it’s done. Finally, select “ASP.NET Core” template and click on Apply. The UI configuration will be displayed and you can do everything from here.

Tasks
Pipeline
Agent Pool=Hosted VS2017
Variables
PHANTOMJS_BIN=$(System.DefaultWorkingDirectory)\src\WebApp\ClientApp\node_modules.bin\phantomjs.cmd

You can see an example of a project in SonarCloud: https://sonarcloud.io/dashboard?id=devpro.demo.angular-aspnetcore.

4. Create the Continuous Deployment (CD) pipeline

4.1 Create a packaging pipeline (PKG)

CI pipeline is used to continuously check the quality of the code source, it needs to run in Debug mode and be as quick as possible. On the other hand, we need a pipeline to generate an optimized version of the website, only when needed. This is where the packaging pipeline finds its use! (working example here) You can configure the triggers to match your delivery process.

4.2 Create a Azure Web App resource

Creating a new Azure resource is easy to do manually with the portal, but you can also automate it.

4.2 Create a Release Pipeline (CD)

In “Azure DevOps”, go to “Pipelines” > “Releases” and create a new pipeline. The “Azure App Service deployment” is easy to configure and will get you started quickly. (working example here)

Final step is to create a package it and release it, wait for the deployment and “Voilà” ! (https://demo-angular-aspnetcore.azurewebsites.net/).

This is it! If you are working on this stack and have some issues, I hope it will help you find quickly how to fix them. Don’t hesitate to contact me or to leave a comment on this post. Happy coding 😉

bertrand

7 thoughts on “Create an Angular 7 / ASP.NET Core 2.2 application and push it to Azure

  1. Hi Thomas! Can you please provide SonarCloud Preparation step i have similar structure but SonarCloud can check only folders which included in the MSBuild if i choose Sonarscanner with MSBuild and don’t analyse my ClientApp or only ClientApp if i choose standalone scanner.

    Thank you in advance and thank you for this article

    1. Hello, thank you for your comment!
      It’s not easy at first but it’s not complicated once we have the good config.

      I use Azure DevOps and I had to add the following lines in the SonarCloud prepare analysis step (“Integrate with MSBuild” + “Advanced” > “Additional Properties”) :


      sonar.exclusions=**/node_modules/**,**/*.spec.ts,**/e2e/**,**/coverage/**
      sonar.typescript.tsconfigPath=ClientApp/tslint.json
      sonar.typescript.lcov.reportPaths=ClientApp/coverage/lcov.info

      Please look at the Angular configuration files:
      karma.conf.js

  2. Thomas,

    Great write up!

    I have few follow up questions as Ihor did:
    1. In SonarClodu prepare analysis, you are using MSBuild scanner?

    2. does this line allow the SoanrCloud to scan the Angular code?sonar.typescript.tsconfigPath=ClientApp/tslint.json

    3. Just wonder for best practice, we should skip node_modules folder? good for security?

    sonar.exclusions=**/node_modules/**,**/*.spec.ts,**/e2e/**,**/coverage/**

    1. Thank you Dennis!

      1. SonarCloud is using MSBuild behind the scene yes. You can see it in the Azure CI Pipeline definition: https://github.com/devpro/aspnetcore-angular-sample/blob/master/.azure/pipelines/ci.yml > task: SonarCloudPrepare@1
      This is what is recommended by SonarSource for .NET Core projects (very easy to use!) but you don’t have to care about MSBuild at all. What is really important is to have .NET CLI commands working on your solution

      2. SonarSource hasn’t been designed to have such cross techno scans but it works (see this thread https://community.sonarsource.com/t/one-repo-two-projects-different-languages/5108).
      For Angular (TypeScript files in particular), we just have to set some configuration values to have a static scan at the end (very different behavior from what is done for .NET but there are compatible).
      The two lines are needed to gather information on test run executions (reference the tslint file for coding conventions and lcov to have results and code coverage):
      sonar.typescript.tsconfigPath=ClientApp/tslint.json
      sonar.typescript.lcov.reportPaths=ClientApp/coverage/lcov.info

      3. sonar.exclusions parameter is a way to say to Sonar to not look at specific files/folders if there are not part of “our code”. Yes you should definitely add node_modules (NPM packages), otherwise you’ll get scan results of open source libraries. It can be interesting (for the fun of it) but it will hide your proper code results.

      If you have other questions, feel free to ask 🙂

      1. Hi Bertrand,

        Thanks for your prompt reply and sharing the ymal pipeline!

        We have similar tech stack: Angular (frontend), .Net Core (backend), Azure DevOps for CICD, but we are using SonarQube instead of SonarCloud.

        I am having issue to use SonarQube to scan both Angular and .Net core source code in bone build definition and upload the result to one SonarQube project.

        I know if i use scannerMode: “CLI”, I will be able to scan the Angular code, but not .Net Code code. If i use scannerMode: ‘MSBuild’, I can only scan .Net Core and not Angular. Therefore, I was surprised how you use scannerMode: ‘MSBuild’ to scan both Angular and .Net Core code.

        – task: SonarQubePrepare@4
        inputs:
        SonarQube: “SonarQube Production”
        scannerMode: “CLI”
        configMode: “manual”

        For your answer for #2 above, can you please elaborate more?

        I realize you pipeline runs a ng lint command and in SonarQube you specify sonar.typescript.tsconfigPath=ClientApp/tslint.json. Does this just tell SonarQube to scan the Angular code using the rules defined in tslint.json?

        Any info is appreciated!

        Thanks!
        Dennis

        1. Hi Dennis,

          Thank you for explaining the context, always nice to know!

          I have been using a private SonarQube instance hosted on an Azure VM but I don’t have an example of a .NET/Angular project on it.

          SonarCloud and SonarQube extensions on Azure DevOps do sometimes “dark magic” (unexplained actions) so we can only guess about the behavior 🙂

          My understanding is the following:

          – Scanning different technical stack with Sonar is not officially supported, but works in some cases like the one of this article with SonarCloud
          – As you said, if you use CLI mode you cannot scan .NET code so it’s not an option 🙁
          – Sonar MSBuild is only used to gather intel from .NET command execution (like build, test) but you can add extra properties to try to gather information on another language such as Angular files (it’s not MSBuild that will scan Angular files)
          sonar.sources property is very important to tell where to look but I think it cannot be set when using MSBuild
          – You can use the Sonar CLI directly from the command line, without the Azure DevOps extensions, but I was not able to achieve the same results (in particular decorating PR on GitHub)
          – File structure seems to matter, this articles deals with an Angular app inside a .NET project, I have another repo with separated directories and I’m not able to get the same integrated results (keep-track/.azure/pipelines/ci.yml)

          Regarding your questions about sonar.typescript.tsconfigPath, this is my assumption yes.

          Hope this helps…
          Bertrand

  3. Thanks for your help Bertrand!

    For now, I will just scan Angular code and .Net Core in different agent/job and upload the results to 2 SonarQube projects.

Leave a Reply

Your email address will not be published. Required fields are marked *