Scott Hanselman

ASP.NET Single Page Applications Angular Release Candidate

January 08, 2018 Comment on this post [22] Posted in DotNetCore | Javascript
Sponsored By

I was doing some Angular then remembered that the ASP.NET "Angular Project Template" has a release candidate and is scheduled to release sometime soon in 2018.

Starting with just a .NET Core 2.0 install plus Node v6 or later, I installed the updated angular template. Note that this isn't the angular/react/redux templates that came with .NET Core's base install.

I'll start by adding the updated SPA (single page application) template:

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.0.0-rc1-final

Then from a new directory, just

dotnet new angular

Then I can open it in either VSCode or Visual Studio Community (free for Open Source). If you're interested in the internals, open up the .csproj project file and note the checks for ensuring node is install, running npm, and running WebPack.

If you've got the Angular "ng" command line tool installed you can do the usual ng related stuff, but you don't need to run "ng serve" because ASP.NET Core will run it automatically for you.

I set development mode with "SET ASPNETCORE_Environment=Development" then do a "dotnet build." It will also restore your npm dependencies as part of the build. The client side app lives in ./ClientApp.

C:\Users\scott\Desktop\my-new-app> dotnet build
Microsoft (R) Build Engine version 15.5 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

Restore completed in 73.16 ms for C:\Users\scott\Desktop\my-new-app\my-new-app.csproj.
Restore completed in 99.72 ms for C:\Users\scott\Desktop\my-new-app\my-new-app.csproj.
my-new-app -> C:\Users\scott\Desktop\my-new-app\bin\Debug\netcoreapp2.0\my-new-app.dll
Restoring dependencies using 'npm'. This may take several minutes...

"dotnet run" then starts the ng development server and ASP.NET all at once.

My ASP.NET Angular Application

If we look at the "Fetch Data" menu item, you can see and example of how Angular and open source ASP.NET Core work together. Here's the Weather Forecast *client-side* template:

<p *ngIf="!forecasts"><em>Loading...</em></p>

<table class='table' *ngIf="forecasts">
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.dateFormatted }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>

And the TypeScript:

import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
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));

interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;

Note the URL. Here's the back-end. The request is serviced by ASP.NET Core. Note the interface as well as the TemperatureF server-side conversion.

public class SampleDataController : Controller
private static string[] Summaries = new[]
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"

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)]

public class WeatherForecast
public string DateFormatted { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }

public int TemperatureF
return 32 + (int)(TemperatureC / 0.5556);

Pretty clean and straightforward. Not sure about the Date.Now, but for the most part I understand this and can see how to extend this. Check out the docs on this release candidate and also note that this included updated React and Redux templates as well!

Sponsor: Scale your Python for big data & big science with Intel® Distribution for Python. Near-native code speed. Use with NumPy, SciPy & scikit-learn. Get it Today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
January 09, 2018 5:03
does it support latest angular 5.x?
January 09, 2018 6:33
Nice. I hope there will also be for Vue.js and Angular Redux.
January 09, 2018 13:18
Thanks, how these templates differ from templates that ship with .NET Core?
January 09, 2018 13:57
Following the clear and simple steps laid out here tells me all is good, but as soon as I open a browser on port 5000 the console spews error messages, including
Your application is running in Production mode, so make sure it has been published, or that you have built your SPA manually. Alternatively you may wish to switch to the Development environment.

I can build the client app with ng build and run it with ng serve but then there is no API to call.

Using SET ASPNETCORE_Environment=Development doesn't seem to be enough to get the Dev version built. Is there something I've missed?
January 09, 2018 17:13
@softboy 99 - Yes, this template is based on Angular 5. The fetchDataComponent.ts class is using HttpClient to call the Web APIs. This is new in Angular 5 as @angular/http library is deprecated. HttpClient provides high-level abstractions for application programming.
January 09, 2018 17:41
Are you aware of any templates that easily add the authentication into an Angular SPA like the default ASP.NET core template has? In particular, the integrated authentication combined with the option of using OAuth providers such as Facebook, Microsoft, Google, etc.
January 09, 2018 18:21
You should move the HTTP call to the NgOnInit method. Making http calls in the constructor is discouraged.
January 09, 2018 18:37
So I take it we can now use the Angular CLI with an core project without any other wiring necessary?
January 09, 2018 18:42
I was wondering how anyone could describe 38C as mild but now see it is just picking a random summary!
January 09, 2018 20:49
Is there a reason why the new templates are still defaulting to returning simple types like IEnumerable on GETs rather than IHttpActionResult?
January 10, 2018 1:03
When I try the new template everything works fine, debuging the client side code with Visual studio 2017, for example when I set a breakpoint in counter.component.ts it doesn't get hit. When I create a new SPA (angular) .net CORE web app using visual studio it uses the old template, and I can debug my breakpoints in counter.component.ts get hit.
Why is that?
Does anyone else have the same issue?
January 10, 2018 8:02
Hi Scott, I developed a multi page web based time clock app - <a href=">OnTheClock</a> using traditional ASP.NET web forms. It has over 100 pages, possibly over 200 including blog posts. Where do you think the limit is on single page sites? Should we consider sites with multiple "single pages" Im not sure. Any thoughts? Thanks ~Dean
January 10, 2018 19:39
Scott, I'm a little confused. I installed the templates, but saw Aurelia was missing from the list. I was sure I'd seen it there before. I found the command I'd installed it with last time:

dotnet new --install "Microsoft.AspNetCore.SpaTemplates::*"

So, which is the definitive SPA template collection from Microsoft? Do these templates clobber each other when grabbing names or do they derive ownership of a name from placement in github (for example). How does it all work? SO MANY QUESTIONS
January 11, 2018 19:41
Marko. My VS2017 javascript debugger also not work.
January 11, 2018 19:42
Marko. My VS2017 javascript debugger also not work.
January 13, 2018 2:05
@Oisin Grehan, I wondered about the same things. This is at least a partial answer:
January 14, 2018 4:04
“Any individual developer can use Visual Studio Community to create their own free or paid apps.”. It does not say anything about open source.
January 14, 2018 17:30
Struggling with the same issue as @Brian. Not sure what the workaround is I've tried a few different things but may have to revert to setting up manually which is a shame as this looks like a really quick way to bootstrap a project!

fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0] An exception was thrown attempting to execute the error handler. System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
January 15, 2018 21:05
This is super cool. I'm looking forward to seeing what the differences between the Release Candidate and the "standard" SPA templates is.

I might even have to upgrade my SPA demo project "The Discworld Disorganiser" to the Release Candidate, too.
January 17, 2018 16:48
@Brian, @Max

I had this issue too when attempting to run from a Powershell prompt; it seems SET here isn't going to work, instead I used


And that did the trick for me, hopefully it will work for you too.
January 18, 2018 19:50
Hi, interesting article, im having issues adding a new service, i added to the provider array in app.module providers: [BrokerfakeService], but when i pass it to the constructor constructor(public brokerService: BrokerfakeService) of the component i get this error trying to run ng build
ERROR in ./app/services/brokerfake.service.ts
Module build failed: Error: \Desktop\Producer Search\producer-search\ClientApp\src\app\services\brokerfake.service.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
at AngularCompilerPlugin.getCompiledFile (\Desktop\Producer Search\producer-search\ClientApp\node_modules\@ngtools\webpack\src\angular_compiler_plugin.js:656:23)
at plugin.done.then (\Producer Search\producer-search\ClientApp\node_modules\@ngtools\webpack\src\loader.js:467:39)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
@ ./app/components/broker/broker.component.ts 14:0-70
@ ./app/app.module.ts
@ ./main.ts
@ multi ./main.ts
January 21, 2018 20:20
Great post Scott, you help me a lot,


Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.