ASP.NET Core Angular project template overview

Searching on the internet we can find plenty of blog posts that describe how to use the default built-in ASP.NET Core Angular project template, however they don’t show how it differs from the other templates. In this post I would like to collect and look at these basic differences and show why they are needed and how they work.

Prerequisites

  • Visual Studio 2019
  • ASP.NET Core 2.2
  • Node.js

The built-in Angular template is a convenient starting point for ASP.NET Core applications using Angular as client-side framework. The initial project includes two separate applications in one project. It is equivalent to creating an ASP.NET Core project for the backend and an Angular SPA to act as a UI. It produces a fully functional initial app that fetches data from the server. In Visual Studio the two applications can be built, published and hosted as a single unit in a convenient way.

How does it work as a single unit?

Usually, to build an Angular application and serve it locally we use ng serve in the Angular CLI. The app then builds and is being served by a local Angular CLI web server. In Visual Studio as a default project setting we don’t need to do it manually during development. It is enough to run the ASP.NET Core app in the usual way with Start Debugging (F5). The ASP.NET Core app deals with both parts of the application, it creates its own Angular CLI instance and invokes the ng serve command in the background to serve the Angular app, thus basically executing the usual process in an automated way. Although this convenient solution makes it easy to launch the app, it may also have a disadvantage. If you need to modify and restart the backend, it also indicates the restart of the Angular CLI server each time, which can be a nerve-rack in case of frequent changes. Fortunately, this default behavior can be overridden, and the two applications can be started independently.
All we have to do is change the following configuration in Startup class in the Configure method:

//spa.UseAngularCliServer(npmScript: "start");
  spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");

This will set up a proxy address for the development server, so we can start the Angular application manually, separately from the ASP.NET Core backend. In command prompt navigate to the ClientApp folder and start the application:

cd ClientApp  
npm start  

What are the differences compared to other ASP.NET Core templates?

The most obvious difference is the ClientApp subdirectory. The ClientApp directory contains a standard Angular CLI application. The generated app uses Angular 6 and it has almost the same project structure as the default one generated by Angular CLI, with slightly differences. It has a Bootstrap based UI and a basic routing example. Unlike the app generated by Angular CLI, the initial app has 4 additional components:
alt

  • nav-menu: a simple component for the navigation bar, that contains the router links to different pages

  • home: simple static html view for home page

  • counter: implements a simple counter on client side

  • fetch-data: it is a bit more interesting component than the previous ones. This component demonstrates fetching data from the ASP.NET Core backend service using HttpClient and displays them on a separate page.

The HTTP get request is in the constructor of the component, directly using the HttpClient class.

export class FetchDataComponent {  
   public forecasts: WeatherForecast[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(baseUrl +
    'api/SampleData/WeatherForecasts').subscribe(result => {
       this.forecasts = result;
    }, error => console.error(error));
  }
}

Side note: It works fine in the sample app, but data access rarely stays this simple. The best practice is to use separate services for data access in lifecycle methods and use these services in components to avoid complex and crowded components. The constructors should be as simple as possible.

Let's look at how the ASP.NET Core application differs from other initial projects.

As usual, the Startup class contains the configuration of the ASP.NET Core application. The ConfigureServices method configures the Dependency Injection container and the Configure method configures the middleware pipeline.

Services registered in DI container
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);  

Adds MVC services to the DI container, where SetCompatibilityVersion tells which version changes are available.

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

Registers the SPA service to the DI container to provide static files to be served for a SPA. The configuration.RootPath specifies the directory from which static SPA scripts/files/images will be served in production environment. If the specified directory does not exist, then the UseSpaStaticFiles middleware (see below) will not serve any static files.

Middleware pipeline
app.UseDeveloperExceptionPage();  

The first middleware is an exception handler middleware, that is capable of catching exceptions and providing a detailed information page about it.

WARNING: Use this only in development mode, because we don’t want to return the complete stack trace in production environment (Exception Shielding)

app.UseExceptionHandler("/Error");  

Exception handler middleware for production environment. Catches and logs exceptions and redirects the request to an error page.

app.UseStaticFiles();  

Enables static files serving from the wwwroot as default folder.

app.UseSpaStaticFiles();  

Enables static files serving for Single Page Application.

app.UseMvc(routes =>  
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");
});

Adds the routing middleware to the pipeline and creates the default route.

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

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

The last middleware adds the SPA middleware to the pipeline and it returns the default page for Single Page Application. In development mode the extension will let you spin up an Angular CLI based web server. The SourcePath option sets the path of the directory that contains the SPA source files during development.

Controllers

The generated application also includes a simple controller (SampleDataController), that has a single action method, that provides random weather forecast data. (The fetch-data Angular component uses this method to get weather forecast data.)

[HttpGet("[action]")]
public IEnumerable<WeatherForecast> WeatherForecasts()  
{
   var rng = new Random();
   return Enumerable.Range(1, 5).Select(index => new WeatherForecast
   {
     DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
     TemperatureC = rng.Next(-20, 55),
     Summary = Summaries[rng.Next(Summaries.Length)]
   });
}
Publishing

In production environment the application has a performance optimized version. It is done automatically by the Ahead-of-Time (AOT) compiler, that minifies and converts the client-side code into efficient JavaScript code during the build process.
After publication, the following directory structure is obtained:
alt The ClientApp/dist directory contains the published files of the Angular application. The wwwroot folder contains static files. In addition to these two, the publish folder also contains the assembly files of the published ASP.NET Core application.

So, what are the advantages of using the Angular template?
  • Managing the two applications as a single unit in one solution
  • You can still use the Angular CLI to control your Angular application
  • Debugging client-side code in Visual Studio
  • Publish and deploy as a single unit in one step
  • Production build automatically uses the AOT
  • Server-side rendering (SSR) support
Conclusion

If you don’t want to completely customize your initial Angular application, and you want to manage the backend and frontend in a same solution as a single unit, then the ASP.NET Core Angular project template can be a convenient starting point. Visual Studio 2019 has a great support for debugging client-side code and using one IDE for developing both sides of the application can make your life easier.
If you wish to create an Angular app from scratch with Visual Studio 2019 and you don’t want to use the project template, you still have the chance to create a simple ASP.NET Core API and using Angular CLI to create a customized client application. Just make sure you register the necessary services and middleware in your Startup class.

Sources