Building Single Page Applications on ASP.NET Core 2.1 with Angular 6 – Part 3: Implementing Open API

This is the third in a series of posts on Building Single Page Applications with ASP.NET Core 2.1 and Angular 6. The previous post provided instructions to upgrade to the latest version of Bootstrap. This post outlines the steps required to implement Open API. Open API, formally known as Swagger API, is an API description format for REST APIs. This post describes using Open API to supercharge our app by creating interactive documentation and generating an Angular client. As an added bonus we will automate this process on build, thereby increasing productivity.

Prerequisites

This post continues on from the previous post, if you haven’t already it’s recommended to start at the beginning. If you would rather just get the code up to this point, follow the steps below:

  1. Open the command prompt and navigate to the location where you would like to create the project. For example, C:\Code.
  2. Execute the following commands to clone the repository:
    git clone --branch v1.1 https://github.com/JasonGT/CodingFlowBuildingSpaSeries --depth 1
    cd CodingFlowBuildingSpaSeries
    git remote rm origin
    
  3. Next restore NuGet dependencies, npm dependencies, and build the project by running this command:
    dotnet build
  4. Run the project to ensure it is working correctly. First, launch the back end by running:
    dotnet run

    Then, open a second command prompt, navigate to the project directory, and launch the front end by running:

    cd ClientApp
    npm start
  5. Open the browser and navigate to https://localhost:5001. If the app is functioning normally, the following page will be displayed:

Preparing the Web API

In this section we will update the Web API in preparation for generating the API specification.

  1. Within the Controllers sub-directory, open the SampleDataController.cs file for editing
  2. Add the ApiController attribute to the SampleDataController class as follows:
    [ApiController]
    [Route("api/[controller]")]
    public class SampleDataController : Controller
  3. Save the file, and then rebuild the application by running dotnet build at the command line.

Without the ApiController attribute, the SampleDataController will not be included when we generate the API specification in the following section.

Generating an API Specification

This section details the steps required to generate an API specification. In this case, the specification will be a file named swagger.json and written in JSON format. The specification describes the available endpoints, operation parameters, authentication methods, contact information, license, terms of use, and other information.

  1. Download, install, and launch NSwagStudio.
  2. Create a new NSwag configuration file by clicking File | New
  3. Under Input: Swagger Specification, set Runtime to NetCore21
  4. Select the ASP.NET Core via API Explorer (new) tab
  5. Under Project, set Project file path to the path of the CodingFlow.csproj project file. For example, C:\Code\CodingFlowBuildingSpaSeries\CodingFlow.csproj
  6. Ensure that NoBuild is checked
  7. Set Default Property Name Handling to CamelCase
  8. Under Swagger Information, set Title to Coding Flow API
  9. Set Output file path to a new swagger.json file within wwwroot/swagger. For example, C:\Code\CodingFlowBuildingSpaSeries\wwwroot\swagger\swagger.json
  10. Set Output Type to OpenApi3
  11. Click File | Save, name the file nswag.json and save it to the project directory. For example, C:\Code\CodingFlowBuildingSpaSeries\nswag.json
  12. Click Generate Files. This will generate the specification document within wwwroot/swagger/swagger.json

In this section NSwagStudio was used to generate an API specification based on the Web API. The API specification will be used in the following sections.

Adding and Configuring Swagger UI

This section describes the steps to add Swagger UI to the app. Swagger UI allows anyone – be it your development team or your end consumers – to visualise and interact with the API’s resources without having any of the implementation logic in place. It’s automatically generated from your API specification, created in the previous section, with the visual documentation making it easy for back end implementation and client side consumption.

  1. Open the command prompt and navigate to the project directory
  2. Install the NSwag.AspNetCore package. Run the following commands:
    dotnet add package NSwag.AspNetCore
    dotnet restore
  3. Within the project directory, open Startup.cs and update as follows. Import the NSwag.AspNetCore; namespace:
    using NSwag.AspNetCore;

    Within the Configure method, just after the line app.UseSpaStaticFiles, insert the following:

    app.UseSwaggerUi3(settings =>
    {
        settings.SwaggerRoute = "/swagger/swagger.json";
    });
  4. Run the project to ensure it is working correctly. First save all changes, then launch the back end by running:
    dotnet run

    Then, open a second command prompt, navigate to the project directory, and launch the front end by running:

    cd ClientApp
    npm start
  5. Open the browser and navigate to https://localhost:5001/swagger. If everything has been configured correctly, the following page will be displayed:

Take a moment to explorer Swagger UI and the features that it provides. A tool such as this is a valuable resource for all users of your API. In this section Swagger UI was installed and configured to reference the generated API specification.

Generating an Angular TypeScript Client

This section includes steps to generate an Angular TypeScript client based on the API specification. To do so, additional changes will be made to the NSwag configuration file created previously. Recall the file contains the necessary configuration to generate the API specification. When we are finished, the configuration file will include the settings to generate both the API specification and the Angular TypeScript client(s).

  1. Switch back to NSwagStudio
  2. Click File | Open, and select the existing nswag.json configuration file
  3. Under Outputs (left side), check TypeScript Client
  4. Select the TypeScript Client tab
  5. Select the Settings side tab
  6. Set TypeScript Version to 2.7
  7. Under Client, set Template to Angular
  8. Under Angular, set RxJs Version to 6.0
  9. Set HTTP service class to HttpClient
  10. Set Injection token type to InjectionToken
  11. Check Generate interfaces for Client classes
  12. Under Output, set Output file path to new app.generated.ts file located within ClientApp\src\app. For example, C:\Code\CodingFlowBuildingSpaSeries\ClientApp\src\app\app.generated.ts
  13. Click File | Save, to save the changes to nswag.json
  14. Click Generate Files. This will use the nswag.json configuration to regenerate the specification document (swagger.json) and generate the new Angular TypeScript Client (app.generated.ts)

In this section NSwagStudio was used to manually generate an Angular TypeScript client for the Web API. The client contains a SampleDataClient for accessing the Web API, and a WeatherForecast class and interface, a type defined in the backend. Generating this code improves productivity, as this is code we no longer need to write.

Refactoring the Fetch Data Sample Component

Now that we have generated a client, we can clean up some of the existing code.

First, register the SampleDataClient with dependency injection.

  1. Within ClientApp/src/app, open app.module.ts for editing
  2. Import the client by adding this line:
    import { SampleDataClient } from './app.generated';
  3. Register the client by updating the providers as follows:
    providers: [SampleDataClient],

Next, update the fetch data component to use the new client.

  1. Within ClientApp/src/app/fetch-data, open fetch-data.component.ts
  2. Update as follows:
    import { Component } from '@angular/core';
    import { SampleDataClient, WeatherForecast } from '../app.generated';
    
    @Component({
      selector: 'app-fetch-data',
      templateUrl: './fetch-data.component.html'
    })
    export class FetchDataComponent {
      public forecasts: WeatherForecast[];
    
      constructor(client: SampleDataClient) {
        client.weatherForecasts().subscribe(result => {
          this.forecasts = result;
        }, error => console.error(error));
      }
    }
    

In this section the Fetch data component was refactored. The manually created WeatherForecast interface was replaced with the generated version. The code that interacted with HttpClient was removed and replaced with the generated SampleDataClient. The result – a much simpler component with fewer lines of code.

Automation with MSBuild

Up to this point the generation of the API specification and TypeScript client has been a manual process driven by NSwagStudio. This is problematic, since changes in the Web API will not be reflected in the API specification or TypeScript client unless the process is run again, every time the Web API changes. The good news is, this process is easy to automate. In this section the process will be automated using NSwag and MSBuild.

  1. Open the command prompt and change to the project directory. For example, C:\Code\CodingFlowBuildingSpaSeries
  2. Add and restore the NSwag.MSBuild package. Run the following commands:
    dotnet add package NSwag.MSBuild
    dotnet restore
  3. Within the project directory, open CodingFlow.csproj for editing
  4. At line 35, insert the following element:
    <Target Name="NSwag" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
      <Copy SourceFiles="@(Reference)" DestinationFolder="$(OutDir)References" />
      <Exec Command="$(NSwagExe_Core21) run /variables:Configuration=$(Configuration)" />
      <RemoveDir Directories="$(OutDir)References" />
    </Target>
    
  5. Build the solution running the dotnet build command from the project directory. You should see the following output:

The API specification and TypeScript client are now automatically generated when running dotnet build or dotnet watch run and reflect any changes made to the Web API.

Source Code

If you ran into any issues, you might like to download a completed version of source code here; Coding Flow on GitHub. If that doesn’t help, please be sure to post a comment below.

Next Steps

In this post, I have provided an overview of implementing Open API for our Web API, including automatically generating the API specification and TypeScript client for our Angular SPA. If you would like to learn more about any of these technologies, take a look at the following resources:

Thanks for reading, please feel free to post any questions or comments below.