Scott Hanselman

ASP.NET Single Page Applications Angular Release Candidate

January 8, '18 Comments [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
v8.9.4
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">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.dateFormatted }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>

And the TypeScript:

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

@Component({
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.

[Route("api/[controller]")]
public class SampleDataController : Controller
{
private static string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

[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)]
});
}

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

public int TemperatureF
{
get
{
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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Tuesday, 09 January 2018 01:03:11 UTC
does it support latest angular 5.x?
softboy 99
Tuesday, 09 January 2018 02:33:12 UTC
Nice. I hope there will also be for Vue.js and Angular Redux.
Tuesday, 09 January 2018 09:18:40 UTC
Thanks, how these templates differ from templates that ship with .NET Core?
Tuesday, 09 January 2018 09:57:53 UTC
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?
brian
Tuesday, 09 January 2018 13:13:18 UTC
@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.
Tuesday, 09 January 2018 13:41:45 UTC
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.
Tuesday, 09 January 2018 14:21:39 UTC
You should move the HTTP call to the NgOnInit method. Making http calls in the constructor is discouraged.
Cody Mullins
Tuesday, 09 January 2018 14:37:15 UTC
So I take it we can now use the Angular CLI with an asp.net core project without any other wiring necessary?
Adam
Tuesday, 09 January 2018 14:42:36 UTC
I was wondering how anyone could describe 38C as mild but now see it is just picking a random summary!
Paul
Tuesday, 09 January 2018 16:49:29 UTC
Is there a reason why the new templates are still defaulting to returning simple types like IEnumerable on GETs rather than IHttpActionResult?
Marc Ziss
Tuesday, 09 January 2018 21:03:48 UTC
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?
Marko
Wednesday, 10 January 2018 04:02:00 UTC
Hi Scott, I developed a multi page web based time clock app - <a href="https://www.ontheclock.com>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
Wednesday, 10 January 2018 15:39:24 UTC
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
Thursday, 11 January 2018 15:41:56 UTC
Marko. My VS2017 javascript debugger also not work.
Marko
Thursday, 11 January 2018 15:42:54 UTC
Marko. My VS2017 javascript debugger also not work.
Mark Hotyakov
Friday, 12 January 2018 22:05:39 UTC
@Oisin Grehan, I wondered about the same things. This is at least a partial answer: http://fiyazhasan.me/about-updated-spa-templates-from-asp-net-core/
dabide
Sunday, 14 January 2018 00:04:47 UTC
“Any individual developer can use Visual Studio Community to create their own free or paid apps.”. It does not say anything about open source.
Mark
Sunday, 14 January 2018 13:30:26 UTC
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.
Max
Monday, 15 January 2018 17:05:34 UTC
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.
Wednesday, 17 January 2018 12:48:12 UTC
@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

$env:ASPNETCORE_ENVIRONMENT="Development"


And that did the trick for me, hopefully it will work for you too.
Steve
Thursday, 18 January 2018 15:50:30 UTC
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
Dennis
Sunday, 21 January 2018 16:20:59 UTC
Great post Scott, you help me a lot,

Thanks
Comments are closed.

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