Building Single Page Applications on ASP.NET Core 2.2
The recently released ASP.NET Core 2.2 includes many improvements such as updated SPA templates. The templates can be used to build single page apps with Angular 6 + Angular CLI or React 16 + Create React App. These templates come configured with Bootstrap 4.
This post will cover getting started, productivity tips, and steps to implement Open API using NSwag.
Note that this post consolidates content from the previous series, Building Single Page Applications on ASP.NET Core 2.1 with Angular 6.
Let’s get started.
Prerequisites
To develop apps using the new project templates, ensure you meet the follow prerequisites.
- .NET Core SDK (2.2 or later)
- Node.js (6 or later)
- Set ASPNETCORE_Environment to Development
Check the .NET Core version by running this command:
dotnet --list-sdks
Check the node version by running this command:
node -v
Getting Started
Creating a new SPA with ASP.NET Core is easy. There are three project templates available. ASP.NET Core with:
- Angular (angular)
- React.js (react)
- React.js and Redux (reactredux)
Create a new SPA using one of the above templates by executing the following command:
dotnet new [short name]
Choosing either angular, react, or reactredux as the short name. Next, launch the application by running the following command:
dotnet run
Note the application may take a few minutes to load, as on first run it will restore the npm dependencies.
Once complete, launch the browser and navigate to https://localhost:5001. Take a moment to explore the new app, as it includes an overview of technologies and features along with a couple of sample components.
Productivity Tips
Run the front end independently
As per the documentation, the project is configured to start the front end in the background when ASP.NET Core starts in development mode. This feature is designed with productivity in mind. However, when making frequent back end changes productivity can suffer as it takes up to 10 seconds to launch the application after a back end change.
You can launch the front end independently by updating the Configure
method within the Startup
class.
For the Angular template, update as follows:
// spa.UseAngularCliServer(npmScript: "start");
spa.UseProxyToSpaDevelopmentServer("https://localhost:4200");
For the React templates, update as follows:
// spa.UseReactDevelopmentServer(npmScript: "start");
spa.UseProxyToSpaDevelopmentServer("https://localhost:3000");
Then, to launch the application, open a command line to start the front end:
cd ClientApp
npm start
Next, open a second command line and start the back end:
dotnet run
This will ensure your application will launch quickly when making either front end or back end changes.
Launch the back end with dotnet watch
Currently, changes to back end files require restarting the ASP.NET Core server. We can avoid this altogether by running:
dotnet watch run
The watch tool monitors backend files for changes, automatically building and restarting the server when changes are detected. Should the build fail, the tool simply waits for a new change, rebuilds, and continues normally.
By running the front end independently and launching the back end with dotnet watch, changes to the front end and back end will be built and available immediately, leaving you free to write more code!
Level Up
In this section, we will take your development to the next level. We will look at automating a number of processes including generating API clients, and reducing the amount of code you need to write.
Reviewing the FetchDataComponent
When building Single Page Applications, front end / back end communication is a major factor. Take a look at the following example:
The diagram above illustrates communication for the sample:
- On the front end, using the
HttpClient
theFetchDataComponent
requests weather forecasts from the back end - The back end responds by providing a response of type
WeatherForecast[]
- The front end receives the response, maps the back end type to a matching type on the front end, and displays the results
While relatively simple, the sample component illustrates numerous issues:
- Requires knowledge of API the developer must be familiar with the APIs capabilities
- Hard-coded URLs the sample component uses hard-coded URLs to access the API
- Duplication of back end types the
WeatherForecast
type is created manually on the front end and back end (violates DRY) - Breaking changes are hard to detect changes to the backend API endpoints and associated types will not be automatically detected by the front end
In this section we will resolve all of these issues by implementing Open API with NSwag.
Generate an API specification
Open API, formally known as Swagger API, is an API description format for REST APIs. In this section we will use Open API to supercharge our app by creating interactive documentation and generating a front end client. As an added bonus we will automate this process on build, thereby increasing productivity.
Update the SampleDataController
. Within the Controllers sub-directory update the SampleDataController
to include the ApiController
attribute:
[ApiController]
[Route("api/[controller]")]
public class SampleDataController : Controller
This ensures that SampleDataController
will be included in the API specification. Generate the API specification. The API specification describes the available endpoints, operation parameters, authentication methods, contact information, license, terms of use, and other information.
Install and launch NSwagStudio. NSwagStudio is part of the NSwag project, which provides tools to generate API specifications from existing Web API controllers and client code from these API specifications.
We will use NSwagStudio to generate an API specification by first creating an NSwag configuration. Ensure you are working with a new configuration by clicking File | New.
Define the new configuration as follows:
Runtime | NetCore21. Works fine with .NET Core 2.2. |
Generator | ASP.NET Core via API Explorer (new) |
Project file path | Browse to and select the SPA project .csproj file |
NoBuild | Checked. NSwagStudio will not build the app before generating the specification. |
Default Property Name Handling | CamelCase |
Output file path | This is the file path to the new API specification file. Recommend to add it to wwwroot, e.g. C:CodeAwesomeSpawwwrootdocsapi-specification.json. |
Output type | OpenAPI 3 |
Save the NSwag configuration file. Click File | Save, name the file nswag.json and save it to the project directory, e.g. C:CodeAwesomeSpanswag.json.
Generate the API specification. Click Generate Files to generate the specification document within wwwroot.
Add and configure Swagger UI
Now that we have a API specification we can utilise Swagger UI, a tool to visualise and interact with the API’s resources without having any implementation logic in place.
Install the NSwag.AspNetCore package. From the project directory, run the following command:
dotnet add package NSwag.AspNetCore
Add and configure Swagger UI.
Open Startup.cs and import the following namespace:
using NSwag.AspNetCore;
Within Startup.Configure
, just after app.UseSpaStaticFiles
, insert the following:
app.UseSwaggerUi3(settings =>
{
settings.SwaggerUiRoute = "/docs";
settings.SwaggerRoute = "/docs/api-specification.json";
});
Launch the project and navigate to https://localhost:5001/docs to view Swagger UI in action.
Generate a TypeScript client (Angular only)
In this section we will update the NSwag configuration to generate an Angular TypeScript client.
Open the existing configuration. Under Outputs check TypeScript Client. Select the TypeScript Client tab followed by the Settings child tab, and update as follows:
TypeScript Version | 2.7 |
Template | Angular |
RxJs Version | 6.0 |
HTTP service class | HttpClient |
Injection token type | InjectionToken |
Output file path | This is the file path to the new TypeScript client file. Recommend adding it to /ClientApp/src/app, e.g. C:CodeAwesomeSpaClientAppsrcappapp.generated.ts. |
Save the NSwag configuration file. Click Generate Files to generate the API specification and the new TypeScript client.
Automating with MS Build
So far the generation of the API specification and TypeScript client has been a manual process driven by NSwagStudio. In this section we will automatic this process. When the project builds, the NSwag CLI will run and generate an updated API specification and TypeScript client.
Install the NSwag.MSBuild package. From the project directory, run the following command:
dotnet add package NSwag.MSBuild
Add a new build task. Open the project .csproj and insert the following element before the PublishRunWebpack
task:
<Target Name="NSwag" AfterTargets="Build">
<Copy SourceFiles="@(Reference)" DestinationFolder="$(OutDir)References" />
<Exec Command="$(NSwagExe_Core21) run /variables:Configuration=$(Configuration)" />
<RemoveDir Directories="$(OutDir)References" />
</Target>
Build the solution. You will see the following output:
The API specification and TypeScript client are now automatically generated when the project builds. In the next section we will refactor the FetchDataComponent and resolve the issues identified earlier.
Refactoring FetchDataComponent (Angular only)
The generated TypeScript client includes a SampleDataClient
that we can use to access the API and fetch weather forecasts. But first we need to register it with dependency injection.
Within /ClientApp/src/app update app.module.ts as follows.
Import the SampleDataClient
.
import { SampleDataClient } from './app.generated';
Register the client by updating the providers.
providers: [SampleDataClient],
Finally, update the FetchDataClient
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));
}
}
This is a massive improvement and previous issues have been resolved. In summary:
Requires knowledge of APIResolved. The developer can now explore the APIs capabilities through Swagger UI or the TypeScript client.Hard-coded URLsResolved. The client manages the URLs, the base URL can be injected.Duplication of back end typesResolved. TheWeatherForecast
type is created in the back end and generated in the front end, changes to the type will be synchronised.Breaking changes are hard to detectResolved. Breaking changes will be detected by Angular CLI when the new TypeScript client is regenerated.
Next Steps
In this post I have provided an overview of Building Single Page Applications on ASP.NET Core 2.2. If you would like to learn more about any of these technologies, take a look at the following resources:
- ASP.NET Core 2.2 overview of new features
- SPA templates learn more about the SPA templates
- Angular docs learn more about Angular
- React docs learn more about React
- NSwag learn more about NSwag
Thanks for reading, please feel free to post any questions or comments below.
The post Building Single Page Applications on ASP.NET Core 2.2 appeared first on Jason Taylor.