Microsoft .NET Core 2.1 + Angular 6: Build and Deploy successfully to Azure

Published on 07 February 2019 by Jos. Reading time: 7 minutes.

In recent months we have seen major improvements in both the .NET core development (.NET core 2.x) and Frontend development (introduction to Angular 6). For a recent customer we decided to combine both frameworks and create a front-end application which runs in the context of Azure. During the development we quickly found out that there are some difficulties to overcome.

At the moment of writing this blog Microsoft still didn’t provide a template with updated versions for the templates. This would not be a problem, since there are already some blogs online which give instructions on how to create a .NET core 2 application with Angular 6, however these don’t give instructions on how to successfully deploy this to the Azure environment. In this blog I will describe what steps are necessary to get a working application published in Azure.

There are currently two possible routes when creating a new .NET project in Visual Studio and include Angular 6. I will present both options, each option has its pros and cons.

 

Preliminary steps

In this blog we make use of Visual Studio Enterprise to create the examples, however there is no reason why this wouldn’t work in Visual Studio Communicty or Visual Studio Code. Before starting with creating a new Visual Studio project make sure that the following tools are installed:

  • Visual Studio 2017 version 15.8.4. or higher (15.8.4 is what I used for the example) or one of the alternative tools (e.g. VS Code) **
  • NPM package manager (https://npmjs.com). The NPM tool is required for compiling installing additional packages required for the Angular app. (6.1.0 is what I used for the example)
  • Node.js is the Javascript runtime used (8.11.1 is what I used for the example)

 

Option 1: Create a project using the ASP.NET Core + Angular template

The following steps should be taken to setup a project when using the ASP.NET core with the Angular template:

Create a new ASP.NET Core Web Application.

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 1

Select the Angular template in the next screen.

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 2

 

If you still have an older version of Visual Studio installed (< 15.8.9) you need to perform the following step of updating to Angular 6. If you have 15.8.9+ you can skip the following step since the new template includes Angular 6.

 

After the Project is generated delete the ClientApp folder in the Solution Explorer, basically we are deleting the generated Angular app again.

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 3

After deleting the folder, open the Package Manager Console, navigate to the Web application folder and execute the following:

          ng new ClientApp

This command will create a new Angular application, but this time based on the latest version (6+). Once this is completed go back to the solution explorer and go to the ClientApp -> package.json file.

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 4

In order to successfully publish the web application to Azure, the following needs to be changed:

In the json file the ‘projects->ClientApp->architect->options->outputPath’ should be changed to “dist” instead of “dist/ClientApp”.

After these changes, first run the application locally, you should be able to see the default Angular welcome screen. If everything runs well, publish the application to an Azure environment, and verify again. You are done with the first option!

 

Option 2: Create a project using the ASP.NET Core without Angular template

The following steps should be taken to setup a project when using the ASP.NET core without the Angular template. This involves more steps to be taken to get everything successfully running, but also gives more insight in the required steps.

Create a new ASP.NET Core Web Application

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 5

This time select the API Controller template, not the Angular. Leave all other options unchanged.

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 6

After this open the Package Manager Console, navigate to the Web application folder and enter the following:

          ng new ClientApp

Microsoft .NET Core 2 + Angular 6 Build and Deploy succesfully to Azure 7

This will generate the Angular application with the latest version (6+). Now compared to the option with the Angular template we now need to do some additional steps. First open the Startup.cs class and add code to the ConfigureService function until it is similar as below.

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });
        }

Next add the code in the next segment until it matches your code in the Configure function. Basically we need to add the Angular specific sections which are:

  • Adding the path to the Angular distribution files
  • Adding the Angular source path variable
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseHttpsRedirection();
            app.UseMvc();

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }
        }

Next since we selected the API template before, make sure to remove the property “launchUrl”: “api/values” in the ‘Properties/launchSettings.json’ file. If you forget to do this step, at launch of the application it will redirect you to the default Controller which you don’t want (you want to direct to the Angular application).

The final step is to make some changes to the project settings file, at least this was necessary with my Visual Studio installation. The original project configuration file as in my project can be seen here.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
    <UserSecretsId>22bbac58-fb9d-4aef-841b-5d123e2318a8</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
  


</Project>

 The sections necessary for generating the Angular javascript files during publishing are missing in the project configuration file. The solution in my case was to add the missing ItemsGroups and Targets manually until it matches the below example. Also make sure the PackageReference for the SpaServices.Extensions is present.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
    <UserSecretsId>22bbac58-fb9d-4aef-841b-5d123e2318a8</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.1.1" />
  </ItemGroup>
  
  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Content Remove="$(SpaRoot)**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>
</Project>

 Now reload the project again, you should be able to run the build and run the project locally, and also publish it to Azure!

 

Conclusion

As mentioned before Microsoft has updated the templates since first writing this blog, so it is now possible to use the templates provided to quickly generate a .NET Core + Angular 6 application. Still the the second option is a valid one if you want to have the most control when setting up your project and want to add the latest version of Angular to the .NET Core application. We will soon see new .NET core (3+) versions being rolled out and also Angular will keep up updating, so the templates will always stay a bit behind. And then its nice to know how to keep both technologies up to date with the mentioned Options.

 

Tags: Azure

Jos

Published by Jos on 07 February 2019

Senior Developer at ETTU since 2018, as such I am involved in the design and implementation of .NET, Azure, front-end and back-end applications. As an engineer my other interests are Robotics, A.I., and Machine learning.

 

Comments? Share them below

Learn more about ETTU

And the way we work