Building a SPA with Aurelia on ASP.NET Core using TypeScript and Sass
Welcome to this blog series that will show you how to write an Aurelia SPA (Single Page Web Application) using TypeScript and Sass. We will also cover serving the SPA with ASP.NET Core as well as writing a Web API on ASP.NET Core.
The planned architecture is to have two ASP.NET Core projects, one that is hosting our SPA with all the front end bits like JavaScript, HTML and CSS. And one ASP.NET Core project hosting our Web API. Also a project hosting our model and a fake repository is needed (this is where the Web API will get it’s data from). So no “real” persistence layer will be used, at least not initially.
The solution will consist of:
- One ASP.NET Core Web Project that will host the Aurelia SPA
- An ASP.NET Core Web Project for the Web API
- A Class library that will hold the data repository, used by the Web API
The “Aurelia SPA built with TypeScript and Sass on .NET Core” Series
These are the parts of this blog post series about building a SPA in Aurelia.
Part I – How to: Build an Aurelia SPA with TypeScript on ASP.NET Core
Part II – How to: Build a Web API on ASP.NET Core for an Aurelia SPA
Part III – How to: Fetching data from a Web API on ASP.NET Core to an Aurelia SPA
Part IV – How to: Creating Aurelia Custom Elements with TypeScript
This post
This first post will contain a little about tooling and list the prerequisites. The we will go thorough the initial setup of the projects in the solution.
Prerequisites
I use Visual Studio for creating the Solution, the Web Projects, the Class Library and work with the c# code in the Web API. You can download the Visual Studio Community edition for free and use that if you like. However, if you prefer not to use Visual Studio, or can’t if you’re on an OS that doesn’t support it, you can always use Yeoman to scaffold out the ASP.NET Core projects and use a different editor.
DOT.NET Core is needed, so install the DOT.NET Core tooling and SDK for using the CLI tools later on.
I personally prefer Visual Studio Code for working with Web Front-end code. Download VS Code for free from their homepage.
For creating the Aurelia SPA, running and debugging it, scaffolding some bits and pieces; we’ll use the Aurelia-CLI. For information on how to install it and the prerequisites for it, see the official documentation.
Node is also needed, if you haven’t got that installed already, check out the the Aurelia CLI pre-reqs where it’s detailed what version is needed.
Project setup
The plan is to have three different projects, one class library holding the data repository, one project hosting the API and one hosting the SPA.
Why having the API in a separate project from the SPA?
In a production scenario, the API shouldn’t be hosted in the same project as the SPA. For learning purposes it is ok to keep it simple, but why not break the projects apart and see if anything unexpected pops up? 🙂
Solution and Project Creation
First let’s create a blank solution to hold all the projects. Then we’ll add a Web Project, a Class Library and a project for our Web API.
- Open Visual Studio and select “New Project”
-
Under Templates > Other Project Types > Visual Studio Solutions we find the Blank Solution option, select it, choose a name for your solution and a location on disc to store it.
-
Right click the solution in the Solution Explorer window and click Add > New Project…. Select the ASP.NET Core Web Application (.NET Core) project template. Give it a name and click OK.
-
In the following dialogue, choose the Empty template and click OK.
- Time to create the Web API project. Repeat the same steps as in step 3 above but give it a different name. Ending the name with API or WebAPI makes it easy to identify in the solution.
-
In the next dialogue, choose the Web API project template.
-
Next up, we’re adding the class library that will hold the model and a repository. Right click the solution in the Solution Explorer window and click Add > New Project…. Next select the Class Library (.NET Core) located under the .NET Core projects section, name it and click OK.
Creating the Aurelia App
We will use the Aurelia CLI to help us create the SPA app. I will use TypeScript and Sass as my prefered language and styling toolchain for this article series.
-
Open a CLI and navigate into the root of the Web project you created earlier (it’s the same folder where the .xproj file is).
Start the Aurelia project creation using the cli by typing:au new --here
- Select platform – choose option 2, ASP.NET Core
- Select transpiler – choose option 2, TypeScript
- Select CSS processor – choose option 3, Sass
- Configure testing – choose option 1, Yes
- If satisfied with the configuration, choose to create the project by pressing selecting option 1, Yes
- Install project dependencies by selecting Yes
- (Optional) Go get a coffee while waiting for dependencies to download… 🙂
Verify that the Aurelia SPA works and that it is delivered by ASP.NET Core
-
Use the cli to build the Aurelia app by typing:
au build
-
Start the ASP.NET Core Web server by typing:
dotnet run
-
Open a browser and go to http://localhost:5000
Hello World, from ASP.NET Core
The message we’re seeing actually has nothing to do with our Aurelia app, it’s served from the ASP.NET application. If we open the Startup.cs file, we can see the response “Hello World!” being written straight into the context.
app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });
Fixing the Front End Web Project
First off, before we start modifying any code, let’s first add a watcher to the Web Project to give us a smoother development experience. The watcher will keep tabs if any relevant files changes and automatically restart the web server for us.
Then we need to enable the ASP.NET request pipeline to serve the HTML, JavaScript and CSS files produced by our Aurelia SPA.
-
Open the project.json file. Under the tools section, add:
"Microsoft.DotNet.Watcher.Tools": "1.0.0-*"
-
In the CLI, type:
dotnet restore
to download the packages -
Start the app and the watcher by typing:
dotnet watch run
Now all setup with the watcher keeping tabs of our changes, we can start modifying the ASP.NET Core web project to deliver our Aurelia files!
What we need to do is to remove the code that wrote a response straight to the context, and tell the pipeline to serve static files (like HMTL, CSS and JavaScript files).
To make things easier we will also tell the pipeline to handle “default files” which will take care of empty routes for us and point it to our initial index.html that starts our SPA.
Modify the Startup.cs file, and modify the Configure method so that it looks like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseDefaultFiles(); app.UseStaticFiles(); }
After modifying the file and saving, you can see the that the watcher will trigger on the change we made to Startup.cs and restart the app.
Now serving the Aurelia SPA
Refreshing the browser now, still pointing to http://localhost:5000 will show the same message, but it’s actually our Aurelia SPA we’re seeing! Hint – notice the Aurelia title of the tab.
Using the Aurelia watcher
To make sure the Aurelia watcher works (the Aurelia-CLI already has one installed for us!), we could change the project a little and see what happens.
-
Start the watcher in a CLI, navigate to the root of the project and type:
au run --watch
- Update the title in the index.html file located under wwwroot/scripts/, change it from “Aurelia” to “Droid Worx”
- Test the data binding in action by modifying the app.ts file located under the src/ folder. Changing the message from “Hello World!” to “More to come!”.
This will give us the following result:
Not seeing the results?
If you’re not seeing any change after refreshing your window (and have made sure that the watcher actually rebuilt the application?)
It can be the case that the browser is caching the page and hence not reloading it properly. To fix this behavior open F12 Developer Tools to empty the cache or disable it.
How To: Empty the cache in Microsoft Edge
How To: Disable the cache in Chrome
Go to Settings->Preferences-Network and check Disable Cache.
Next part – Web API!
In the next episode we’ll get the Web API going! Building a repository and some models in the Class Library, we’ll see how we can start serving data to our clients.
Get the Code
The code for this blog series is available on my GitHub repo, you can find it here: DWx-Aurelia-dotNETCore
Until next time,
Happy Coding! 🙂
Thanks for this. How would we get auto page reloads with browsersync to work?
Hi Jason,
The way I currently setup the project in the article, it’s not possible as far as I know.
But I do know there are some people out there playing around with browsersync, hot reloading etc.
I will have to look into it and get back with another post if I come up with something good 🙂
Cheers,
Andreas
This works for me:
Replace the “serve” task in “aurelia_project/tasks/run.js” with this:
let serve = gulp.series(
build,
done => {
browserSync({
open: false,
port: 9000,
logLevel: ‘silent’,
proxy: {
target: ‘localhost:5000’
}
}, function(err, bs) {
let urls = bs.options.get(‘urls’).toJS();
console.log(`Application Available At: ${urls.local}`);
console.log(`BrowserSync Available At: ${urls.ui}`);
done();
});
}
);
Indeed, after some fiddling I got that to work as well. Awesome 🙂
I actually tried to get this running during the summer, using the proxy as stated in BrowserSync’s documentation. But at that time I could not get it to work.
Need to add the BrowserSync port to the CORS policy as well to make the example setup in the article work well. I think I’ll write a short post about the setup later.
Thank you so much, Daniel!
Pingback: How to: Build a Web API on ASP.NET Core for an Aurelia SPA - mobilemancer
Did you change the Aurelia default settings build on Port 5000 instead of the default 9000?
When I run “au run –watch” it builds on on a differnt port so breaks the site.
The idea with the project setup is to use ASP.NET Core as the host, and that project defaults to serving the app on localhost:5000.
I didn’t really want to dive into the build concept in the article, but for the purpose of this series it’s quite ok to remove the browsersync dependency from the build scripts.
If you want remove the startup of browsersync after watch/build, just modify the end of aurelia_project/tasks/run.ts:
if (CLIOptions.hasFlag('watch')) {
// run = gulp.series(
// serve,
// watch
// );
run = gulp.series(
build,
watch
);
} else {
// run = serve;
run = build;
}
Pingback: How to: Fetch data from Web API on ASP.NET Core to an Aurelia SPA - mobilemancer
Pingback: How to: Creating Aurelia Custom Elements with TypeScript - mobilemancer
Pingback: Using TypeScript's async/await in Aurelia - mobilemancer
Pingback: How To: Configure and Use the Router in an Aurelia SPA - mobilemancer
Pingback: How To: Style an Aurelia SPA with Sass - mobilemancer
Pingback: Unit Testing and E2E Testing an Aurelia SPA (CLI) - mobilemancer
While the following might not be the appropriate approach, I had issues serving the app-bundle.js and vendor-bundle.js given the directory structure (wwwroot and scripts) being on the same level. Had to add the following lines to my Startup.cs (as per the asp.net core docs on Static Files).
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @”scripts”)),
RequestPath = new PathString(“/scripts”),
EnableDirectoryBrowsing = false
});
Was then able to see ‘Hello World’ from the Aurelia project. DWx.Webb in the above examples.
This alongside app.UseStaticFiles and app.UseDefaultFiles required additional includes. Only issue I am having as of the moment is the ability to be able to run the project from Visual Studio through IIE Express. “tsc” exiting with 1. So CLI it is.
Hey Bill,
Sorry to tell you, but the version of the CLI you are using has has a bug 🙁
The bundles should not end up in /scripts, they should be transpiled in to the wwwroot/scripts folder in ASP.NET Core based projects.
I recommend you get another version of the CLI and setup the project again. Or check the aurelia.json file in my GitHub repo to see how the build target should be defined.
Although, adding a file provider, like you did, is the solution when serving files outside of wwwroot 🙂 But for a basic project, it just shouldn’t be necessary.
As for running the project form Visual Studio you need to turn off the automatic TypeScript compilation. If you do that you should be able to serve the project from IISExpress, if that is your preferred workflow.
Good luck,
Andreas