Scaffolding a modern web application with ASP.NET Core

This post is a walkthrough of putting together a new application in the latest web technologies. Perfect for starting a new project! It’s incredibly easy with the new ASP.NET Core SPA (single-page application) templates.

The stack in use is as follows:

  • Visual Studio 2017 or Visual Studio Code (optional, but nice for intellisense, debugging etc)
  • TypeScript (extends JavaScript with features like classes and types)
  • React (client library for rendering your UI) and Redux (for handling state, allowing debug features like time travel)
  • Webpack (for bundling/minifying your scripts, and hot module replacement)
  • ASP.NET Core – letting us write our server in lovely C#! (Notably, server pre-rendering is available due to the AspNetCore.SpaServices assembly which calls into Node to execute scripts on the server)

Firstly you need to install the .NET Core SDK. The current version is 1.1. You can either install Visual Studio (if you are licensed for that) or just the command line tools. You can later install Visual Studio Code, the free cross-platform Visual Studio, if you like.

Next you need to install Node. If you’ve already got it, update it to the latest version. I found that I had an old version and I was getting bizarre errors until I realised I had to uninstall and reinstall. Node seems like an odd requirement since it’s a web server in itself, and aren’t we using IIS? The reason it’s needed is because we can take advantage of its extensive library of packages, and additionally, ASP.NET Core can use Node silently in the background to execute JavaScript, on the server, for pre-rendering the page. This can be done when you’re using React or Angular 2.

Now comes the fun part. We will use the ASP.NET SPA Services (Single-page application) generator to produce a ready-to-go, pre-configured application based on the client library we want. So, install both SPA Services and the Yeoman generator:

npm install -g yo generator-aspnetcore-spa

Now create a folder for your application, cd into it, and run the generator:

cd c:\appdirectory
yo aspnetcore-spa

You’ll be given a choice about which framework to use in your project:

In my case I picked React with Redux. It then asks if you want the ‘project.json’ or ‘csproj’ project format. csproj is the one to go with if you’re using Visual Studio 2017. Type a project name and you’re done.

Once the process completes you’ll have a project setup and ready to go:

Before running, you will want to switch to development mode. This allows dev features like hot module reloading to work:

set ASPNETCORE_ENVIRONMENT=Development

To run the project, you have two options. Either open the csproj in Visual Studio 2017 and hit F5 to start debugging, or back in your console, run:

dotnet run

Either way the server will start on port 5000, so have a browse of it. There’s a little basic application for you to muck about with:

Click ‘Counter’ and there’s a button that increments a variable:

Now open ClientApp/components/Counter.tsx. This is the TypeScript React component for the counter.  We’ll test out the hot module reloading by editing that component to add another element to the page:

Webpack at this point detects the file change, the client downloads it, and Redux is able to maintain the state and update the page:

Another major win when using a state manager like Redux is Time Travel. Time Travel is when the state of your app is recorded throughout the lifetime of the app, and you can use a timeline to move the state of the app backwards and forwards in time.

To get Time Travel working, you can use the Redux Dev Tools. The dev tools come in two formats: a JavaScript library that you can add to your app, or a Chrome browser extension. Check out this blog post for an explanation of it. Either way, the dev tools look like this:

To try it out, click the ‘Increment’ button a few times. The tools are already recording the state changes and you’ll see the ‘INCREMENT_COUNT’ action appearing along within a timestamp.

Make sure the slider is show by clicking the slider button:

And then just move the slider around to travel through time. You can also click on an individual action in the list on the left to jump to the state at that time.

The slow death of bookmarklets

The Content Security Policy specification, a technology to prevent cross-site scripting attacks, has advanced from Working Draft to Candidate Recommendation. Which is a good thing, but unfortunately has the side effect that bookmarklets are going to stop executing on any web page that implements it.

What’s a bookmarklet?

It’s a small piece of JavaScript embedded in a link. That link is then added to your browser’s bookmarks. When it’s clicked, the script is executed. A bookmarklet always takes the form:

javascript:alert("hello");

the code can, if it wants, load code from any other site into the current pages’ DOM, and execute that instead.

One bookmarklet I use is Instapaper which submits the current page to your ‘read later’ list. And there are loads of bookmarklets to assist web designers.

What’s Content Security Policy?

A W3C specification, call it part of HTML5 if you want to. It’s a collection of new HTTP headers that a page can include to indicate a list of places from which JavaScript should be trusted. Any scripts which do not appear on that whitelist will not be executed, which means the site is well protected against XSS attacks (when the users have supported browsers).

For example, if I’ve got a bit of custom form validation code, then the current domain will need to be whitelisted, and if I’m running Google Analytics, I’ll trust Google too. To trust both locations the appropriate header would look like this:

Content-Security-Policy: script-src 'self' http://www.google-analytics.com

But CSP does other things!

If you include a Content Security Policy header in your page, you’re also saying that the browser should adhere to a few additional security rules:

  • Inline scripts are banned (inside <script> tags in the page) to prevent injection attacks
  • ‘eval’ is ignored, and that includes its use within setTimeout/setInterval
  • The JavaScript: link format is ignored.
That last one is important because that’s what bookmarklets do. Additionally, if the bookmarklet loads an external script to run, that won’t work.

Current browser support

Firefox 4 and Chrome 16. Although, they are using X-Content-Security-Policy and X-WebKit-CSP respectively at the moment.

Current web uses

Twitter claim they’ve rolled it out on their mobile site, but looking at the headers, I can’t see any evidence of it. I found this site which is sending the X-Content-Security-Policy header (the Firefox one) and I can confirm my Instapaper bookmarklet is definitely dead there.

This post focuses on the JavaScript side of the CSP specification, but it can also apply to any other type of resource (fonts, images etc). Have a look at the HTMLRocks page for more info!