Enforce HTTPS everywhere with the HSTS header

Enforce HTTPS everywhere with the HSTS header

With the HTTP Strict Transport Security header you can tell the browser to only use secure HTTP (so HTTPS) for downloading your website's content.

This blog post explains the header, but also how to add the HSTS header to your .NET Core website using the U2U.AspNetCore.Security.Headers package.

So how does it work?

Modern browsers can be instructed about how to handle your content in different ways. You can tell it for example to only download scripts from your web site with the Content Security Policy header. You can also tell it to use HTTPS to download your content.

The HSTS header is a great way to protect against Downgrade attacks and SSL strip attack

The header itself is pretty straighforward. Here's an example:

Strict-Transport-Security:max-age=86400; includeSubdomains; preload;

Options in the HSTS header - the max-age directive

The max-age directive marks the period in which insecure requests cannot be made... The units are in seconds, and the duration is reset on every response of the response header.

You do have the realize that all requests will now use https, including .css, .js, etc...

If you want to get rid of the header (especially during development) you can do so, but it heavily depends on the browser.

For example in chrome go to chrome://net-internals/#hsts Here you can add a domain manually, delete a domain, and query the domain to see the header from that site.

The include-subdomains directive

The scope of the HSTS header can be extended to sub-domains, protecting current and future sub-domains. You do need to be careful with this since it might block pages that don't use HTTPS. This is required for the preload directive.

Trust On First Use (TOFU)

There is of course an obvious problem with this header, generally knows as Trust On First Use, or TOFU. If the attacker can intercept the first interaction, he (or she) can easily strip the header from the response.

The preload directive

To prevent this window of opportunity, you can register your domain (with all subdomains). Browser builders will then add your domain to a list embedded in the browser, which will automatically use HTTPS for your domain. Registering your domain will make it very hard to switch back to HTTP.

To register your domain go to https://hstspreload.appspot.com; this site belongs to the chromium project. It will take some time for your domain to be added to all browsers.

If you want to check if a site is on the preload list: here is the list

Browser compatibility

Goto http://caniuse.com/#feat=stricttransportsecurity to check compatibility. Internet explorer is the unfortunate exception in this list, no support until IE 11...

Adding the HSTS header to your website hosted in IIS

Adding the header is easy when your website is deployed with IIS. Simply add this in configuration:

<system.webServer>
  <customHeaders>
    <add name="Strict-Transport-Security" 
         value="max-age=6000; includeSubdomains;" />
  </customHeaders>
</system.webServer>

Adding the HSTS header in .NET Core

You can easily add the header using the U2U.AspNetCore.Security.Headers package.

After adding the package add this to the Configure method in Startup

app.UseResponseHeaders(builder =>
{
  builder.SetStrictTransportSecurity(new StrictTransportSecurity
  {
    MaxAge = TimeSpan.FromDays(1),
    IncludeSubdomains = true,
    Preload = false
  });
};

You can add any header with this middleware using the builder.SetHeader("Header", "Value") method. But it also contains a couple of convenience methods such as SetStrictTransportSecurity.

Protect your dotnet core website with Content Security Policy

The new Content-Security-Policy HTTP response header helps you reduce XSS risks on modern browsers by declaring what dynamic resources are allowed to load via a HTTP Header.

For example, with the CSP header you can block inline scripts from executing, effectively stopping simple XSS attacks.


What is the Content Security Policy

HTTP headers are used by Servers and Browsers to talk to one another. For example the server can tell the browser what kind of content it is sending using the Content-Type and Content-Length header. Every web page is built-up from different content sources, for example the html comes from the server, but your style might come from a CDN server such as bootstrap. The new Content-Security-Policy is used by the server to tell the browser which content-sources it can use, for example:

Content-Security-Policy:default-src 'self'; style-src 'self' https://ajax.aspnetcdn.com

This header tells the browser to only use html from the server itself, and only to use styles from the server and the aspnetcdn server. Browsers that support CSP will not use any other content sources.

But wait! There is more. You can also tell the browser not to load your content into another page, protecting against Clickjacking. You can use the frame-ancestors directive for that:

Content-Security-Policy:default-src 'self'; script-src 'self' https://ajax.aspnetcdn.com ; style-src 'self' https://ajax.aspnetcdn.com; frame-ancestors 'none';

All the different kinds of content sources and directives can be found here


Using inline scripts with CSP

Maybe you are using some external inline script, such as Google Analytics or Microsoft Application Insights. Normally CSP will block any inline script or style. So how can I use my inline script?

One option would be to use the 'unsafe-inline' content source, but this allows any inline script to execute! Luckily there is another way.

Using hashes to allow inline scripts and styles

When CSP has been enabled, and you have an inline script on your page, your browser will not execute it. You will find in your browser's Console window some remark about it. For example in Chrome:

Refused to execute inline script because it violates the following Content Security Policy directive

Chrome also suggest a way to get around this, and even displays a hash for the inline script:

Either the 'unsafe-inline' keyword, a hash ('sha256-e3wuJEA9ZnrbftKXWc68bpGC5pLCehsGKmy02Qh9h74='), or a nonce ('nonce-...') is required to enable inline execution.

So the solution is to include this hash value in your content sources:

default-src 'self'; script-src 'self' https://ajax.aspnetcdn.com 'sha256-gKHd+pSZOJ3MwBsFalomyNobAcinjJ44ArqbIKlcniQ='; style-src 'self' https://ajax.aspnetcdn.com 'sha256-pTnn8NGuYdfLn7/v3BQ2pYxjz73VjHU2Wkr6HjgUgVU='; frame-ancestors 'none';

As you can see in the example above, you can also use this for inline styles.

Using nonces to allow inline scripts and styles

The mayor disadvantage of the hash is that you need to recalculate and update the hash value whenever you update the script/style. So if you update the script (or dynamically generate it) you will want to use a nonce.

A nonce is a 'number used only once'

You need to generate for each request a unique nonce for each inline script and inline style and include it in the CSP header:

Content-Security-Policy:default-src 'self'; script-src 'self' https://ajax.aspnetcdn.com 'sha256-gKHd+pSZOJ3MwBsFalomyNobAcinjJ44ArqbIKlcniQ=' 'nonce-1LCV8O37L47QVufyugd6rqoebY+OAQGq8iajMbdy3B8='; style-src 'self' https://ajax.aspnetcdn.com 'sha256-pTnn8NGuYdfLn7/v3BQ2pYxjz73VjHU2Wkr6HjgUgVU=' 'nonce-ZUqNLKpiwM9Hru6BjlIx6DtREfGXO2c38CCzMAW6TQ0='; frame-ancestors 'none';

You also need to attribute your scripts and styles with a nonce attribute, matching the nonce from the header.

<script nonce="1LCV8O37L47QVufyugd6rqoebY&#x2B;OAQGq8iajMbdy3B8=">

Adding the CSP header in .NET Core

To make adding the CSP header easy in .NET Core I have built two NuGet packages: U2U.AspNetCore.Security.Headers and U2U.AspNetCore.Security.Headers.TagHelpers.

So start by adding them to your project:

<PackageReference Include="U2U.AspNetCore.Security.Headers" Version="1.1.0" />
<PackageReference Include="U2U.AspNetCore.Security.Headers.TagHelpers" Version="1.1.0" /> 

U2U.AspNetCore.Security.Headers

This package allows you to add headers to your response, such as the CSP header. Call UseResponseHeaders in your Startup.Configure method:

app.UseResponseHeaders(builder =>
{
  ...
}

You can set any header like this:

builder.SetHeader("SomeHeader", "SomeValue")

You can set the CSP header using the SetContentSecurityPolicy method:

builder.SetContentSecurityPolicy(new ContentSecurityPolicy()
  {
    ...
  }

Now select the directives you need with their content sources:

DefaultSrc = new List<string> {
  ContentSecurityPolicy.Source.Self
},
ScriptSrc = new List<string> {
  ContentSecurityPolicy.Source.Self,
  "https://ajax.aspnetcdn.com",
  "'sha256-gKHd+pSZOJ3MwBsFalomyNobAcinjJ44ArqbIKlcniQ='"
},
StyleSrc = new List<string> {
  ContentSecurityPolicy.Source.Self,
  "https://ajax.aspnetcdn.com",
  "'sha256-pTnn8NGuYdfLn7/v3BQ2pYxjz73VjHU2Wkr6HjgUgVU='"
}

And what about nonces?

U2U.AspNetCore.Security.Headers.TagHelpers

Using nonces means that you need to generate a cryptographically randon nonce, and attach it to the header and the script of style tag. This package makes that easy through a nonce taghelper.

If you're not familiar with taghelpers, click this link

First of all enable nonces in Startup.Configure:

builder.SetContentSecurityPolicy(new ContentSecurityPolicy()
{
  SupportNonces = true,

Next add the nonce taghelper to your views. The easiest way is to add following to _ViewImports.cshtml:

@addTagHelper *, U2U.AspNetCore.Security.Headers.TagHelpers

Now look for your inline script and style tag(s) and add the nonce attribute:

<script nonce="true">alert('Use the Nonce!');</script>

Start your website and use the browser debugger to look at the CSP header:

Content-Security-Policy:default-src 'self'; 
script-src 'self' https://ajax.aspnetcdn.com 
'nonce-Gl9JnGKKw9+0+fThsPtVdYtraPLwxWDtB4Qq7qMKH0w=';
style-src 'self' https://ajax.aspnetcdn.com  'nonce-KX0fql/urMHxnZGnDqNoyOljycR/e8nNv2bsjk//sS8='; 

Your script tags should also include the nonce value:

<script nonce="Gl9JnGKKw9&#x2B;0&#x2B;fThsPtVdYtraPLwxWDtB4Qq7qMKH0w=">
  alert('Use the Nonce!');
</script>
<script nonce="stjl3RNNOKDytWwDlWb8Rr2FGmNAmEdykWaCCPc10TQ=">
  alert('Also ok!');
</script>

Does your browser support CSP?

The easiest way to find out is to visit CSP-Browser-Test

But generally, if you are using the latest version of a modern browser, it should support CSP.

Release management with different configurations

So Visual Studio Team Services now has this automatic deployment option, where you can checkin your changes in source control to have the application deployed to a development/testing/production environment automatically. 

But how do you cope with each environment's different configuration? Read on...

What we want

As you are developing locally you probably want to develop on a local database. The easiest way to do this is to have everything in web.config (I am using a web project as an example here, but things are similar for other project types). This way developers can quickly change things locally, for easy testing with different databases, and even see how things work with live (I hope cloned from production) data.

But when deploying to a test environment (and other environments such as production) you want to use a different web.config, preferably NOT containing any production secrets (like the connection string to the production database).

VSTS release management makes this very easy.

How To

Let's say that I have application settings and connection strings that I want to give a different value in development, QA and release:

  <appSettings>
    <add key="Secret" value="DeveloperSecret"/>
  </appSettings>
  <connectionStrings>
    <add name="DB" connectionString="DeveloperDB"/>
  </connectionStrings>

I have already created a Build definition in VSTS, and I am using it to initiate a release with VSTS release management.

In my release definition I have three environments, one for dev, QA and production.

For each environment, click on the ellipsis (...) button and choose Configure variable


Add variables who's key matches the key from appSettings (or name for connectionStrings)


Select your deploy to azure task in release management


Look for the File Transforms & Variable Substitution Options section and make sure you check the XML variable substitution checkbox.


This will make the deployment task replace any key in appSettings and connectionStrings with your variable values.

That's it!

Using Microsoft Fakes with mscorlib.dll


Microsoft Fakes is a tool that allows you to replace any method of any .NET class. This makes it ideal for testing untestable code, for example code that uses DateTime.Now in its implementation...

However when using Microsoft Fakes with mscorlib.dll, the assembly that contains DateTime, you will encounter an error Error CS0234:

The type or namespace name 'EventSourceCreatedEventArgs' does not exist in the 
namespace 'System.Diagnostics.Tracing' (are you missing an assembly reference?)

This actually should not be a problem, because it is actually a sign of something else: that you're faking too much (no pun intended :). Using Microsoft Fakes will generate a fake type for every type in the target assembly, which is very wastefull of resources. You should actually only fake the type you're testing.

Open the fakes file (for example mscorlib.fakes):

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" Version="4.0.0.0"/>
  <StubGeneration>
    <Clear />
  </StubGeneration>
  <ShimGeneration>
    <Clear />
    <Add FullName="System.DateTime!" />
  </ShimGeneration>
</Fakes>

As you can see here, you add each type you want to stub/shim in the <StubGeneration> and <ShimGeneration> section.

For more information about this, you can find more documentation at https://msdn.microsoft.com/en-us/library/hh708916.aspx#BKMK_Configuring_code_generation_of_stubs

Using Razor outside of MVC for building custom middleware or other generation stuff

Recently I have been building some asp.net core middleware which involves generating some html from a collection of elements.

Writing code to generate html is no fun at all, so I decided to see if I could not use Razor outside of the normal MVC stack.

Simple answer: yes! 

I've published this as a package on NuGet.org (scroll down for sources):

U2U.AspNetCore.Mvc.Razor

Use razor to generate files outside of the normal MVC Controller/View chain, for example in your middleware, or for sending dynamic email messages.

All you need is a HttpContext.

To generate contents from Razor as a string

Start by creating a viewModel instance. The ViewModel is used to pass data to the Razor file, ViewData or ViewBag is not supported.

Create a Razor file, using the ViewModel's class as the @model:

@model TestRazor.Models.RazorViewModel

Your message: @Model.Message

Then call the RenderToStringAsync method (which is an extension method on HttpContext) passing the path to the razor file and the viewmodel. You will get the result back as a string.

var viewModel = new RazorViewModel { Message = "Generated from razor!" };
var contents = await HttpContext.RenderToStringAsync("~/Views/Home/Razor.cshtml", viewModel);

To generate Razor contents to the response stream

Start by creating a viewModel instance. The ViewModel is used to pass data to the Razor file, ViewData or ViewBag is not supported.

Create a Razor file, using the ViewModel's class as the @model:

@model IEnumerable<U2U.AspNetCore.NotFound.NotFoundRequest>

<!DOCTYPE html>
<html>
<body>
  <h1>Fix 404s</h1>
  <table>
    <thead id="requestHeader">
      <tr>
        <th class="path">Path</th>
        <th>404 Count</th>
        <th>Corrected Path</th>
      </tr>
    </thead>
    <tbody>
      @foreach (var request in Model)
      {
        <tr class="requestRow">
          <td>@request.Path</td>
          <td>@request.Hits</td>"
          @if (!String.IsNullOrEmpty(request.FixedPath))
          {
          <td>@request.FixedPath</td>
          }
          else
          {
          <td>
            <input type="text" />
            <a href='@string.Format("?path={0}&fixedPath=", request.Path)' class="fixLink">Save</a>
          </td>
          }
        </tr>
        }
      </tbody>
    </table>
  </body>
</html>

Then call the RenderToStringAsync method (which is an extension method on HttpContext) passing the path to the razor file and the viewmodel. The resulting razor content is written to the result stream.

var viewModel = tracker.NotFoundRequests.OrderByDescending(r => r.Hits).ToList();
await context.RenderAsync("~/Views/Shared/NotFound.cshtml", viewModel);

Sources

Sources of this package are available on github repository https://github.com/PeterHimschoot/U2U.AspNetCore.Mvc.Razor

Any bugs, remarks, etc... can always be sent to peter@u2u.be

Simpler checking of arguments with C# 7 throw expressions

Simpler checking of arguments with C# 7 throw expressions

C# 7 has made a simple and important change to C# throw statements. They are now expressions.

So what does that mean for you? It means that now you can check your arguments with a simpler statement.

One such recurring pattern is in the constructor of a class, where you get passed some mandatory dependency. This dependency cannot be null, and then needs to be stored. If the dependency is null, you want to throw an ArgumentNullException.

Here is an example in C# 6

if( context != null )
{
  throw new ArgumentNullException(nameof(context));
}
this.context = context;

Compare this with the C# 7 version:

this.context = context ?? throw new ArgumentNullException(nameof(context));

We assign the context field a value with the null-coalescing operator which takes the left side if it is null (and doesn't evaluate the right side). If the left side is null, it evaluates the right side, which throws an ArgumentNullException.

Way simpler and elegant!

Markdown taghelper

U2U.AspNetCore.Mvc.TagHelpers

Markdown MVC6 taghelper

This taghelper will replace itself with markdown converted to html.

You can learn more about this handy syntax here: https://daringfireball.net/projects/markdown/

You can choose between

  • Path to a markdown file on disk
  • Url to markdown contents
  • Embedded markdown

To convert a local markdown file to html:

<md path="~/md/demo.md">
</md>

To convert some markdown content from the internet use:

<md href="https://applephi.blob.core.windows.net/demo/README.md">
</md>

And of course you can simply embed markdown:

<md class="row">
  ## This is a test

  This is a test

  ```
  With some code
  ```
</md>

Sources

I you're interested in how this packages works, it is available on github at https://github.com/PeterHimschoot/U2U.AspNetCore.Mvc.TagHelpers

Any bugs, remarks, etc... can always be sent to peter@u2u.be

Getting rid of "String based programming" style in dotnet core

String based programming

I really don't like the coding style of using strings instead of identifiers... For example in MVC you can redirect to another action using

RedirectToAction("Index");

However, using the string "Index" instead of the name of the method (an action typically corresponds to a method in MVC right?!) make your code harder to maintain. Renaming the method will not rename the string for example. That is why I like to use

RedirectToAction(nameof(HomeController.Index))

However, this does not work with Controller names. Because of the way routing is implemented, using the full name of the controller confuses routing and you end up with an invalid Uri.

RedirectToAction(nameof(HomeController.Index), nameof(HomeController))

This problem is fixed by U2U.AspNetCore.Mvc.NameOf

U2U.AspNetCore.Mvc.NameOf

This package updates Mvc6 to allows the use of the nameof() keyword in your views

For example, instead of using strings for the name of the controller and action

<a asp-controller="Home" asp-action="Index" class="navbar-brand">Index</a>

you can use nameof()

<a asp-controller="@nameof(HomeController)" asp-action="@nameof(HomeController.Index)" class="navbar-brand">Index</a>

Setup

All you need to do extra is to add a using to your _ViewImports.cshtml

@using WebApplication2.Controllers

and in Startup.ConfigureServices add a call to AddNameOf after the call to AddMvc.

services.AddMvc();
services.AddNameOf();

Sources

I you're interested in how this packages works, it is available on github at https://github.com/PeterHimschoot/U2U.AspNetCore.Mvc.NameOf

Any bugs, remarks, etc... can always be sent to peter@u2u.be

Building the angular.io quickstart with ASP.NET Core

When you start to explore angular 2, probably the best place to start is taking the quick start on angular.io.

In this post I will show you how you can setup the project to use Visual Studio 2015 and ASP.NET Core, since the quick start from angular.io doesn't work as described with ASP.NET Core. Some of the changes are different conventions (putting the libraries in the wwwroot/lib folder for example), and some changes are because we will be using gulp...

 

I will give you step by step instructions on how to setup the project, explanations about why can be found on angular.io.

 

Start by creating a new ASP.NET Core project in Visual Studio:

image

Click OK. In the next screen pick the Empty template.

Open project.json and add a dependency to the StaticFiles package:

"dependencies": {
  "Microsoft.NETCore.App": {
    "version": "1.0.0",
    "type": "platform"
  },
  "Microsoft.AspNetCore.Diagnostics": "1.0.0",
 
  "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
  "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
  "Microsoft.Extensions.Logging.Console": "1.0.0",
  "Microsoft.AspNetCore.StaticFiles": "1.0.0"
},

Save your changes so NuGet will install the package.

Open Startup.cs and add the StaticFiles middleware:

app.UseDefaultFiles(new DefaultFilesOptions
{
  DefaultFileNames = new string[] { "index.html" }
});
app.UseStaticFiles();

Now add a new JSON file to the project (next to project.json) called package.json:

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "postinstall": "typings install",
    "typings": "typings"
  },
  "license": "ISC",
  "dependencies": {
    "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "3.0.0-rc.1",
    "@angular/router-deprecated": "2.0.0-rc.2",
    "@angular/upgrade": "2.0.0-rc.5",
    "angular2-in-memory-web-api": "0.0.15",
    "bootstrap": "^3.3.6",
    "core-js": "^2.4.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "systemjs": "0.19.27",
    "zone.js": "^0.6.12"
  },
  "devDependencies": {
    "typescript": "^1.8.10",
    "gulp": "^3.9.1",
    "path": "^0.12.7",
    "gulp-clean": "^0.3.2",
    "gulp-concat": "^2.6.0",
    "gulp-typescript": "^2.13.6",
    "typings": "^1.3.1",
    "gulp-tsc": "^1.2.0"
  }
}
Save this file to make visual studio do a npm install.
 
image
 

Add another JSON file called typings.json

{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160602141332",
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
    "node": "registry:dt/node#6.0.0+20160807145350"
  }
}
Right-click the Dependencies folder and choose Restore packages. This will install the typings.
 
Now add a gulp configuration file (gulpfile.js):
var ts = require('gulp-typescript');
var gulp = require('gulp');
var clean = require('gulp-clean');
var destPath = './wwwroot/lib/';
// Delete the dist directory
gulp.task('clean', function () {
  return gulp.src(destPath)
      .pipe(clean());
});
gulp.task("scriptsNStyles", () => {
  gulp.src([
          'core-js/client/**',
          'systemjs/dist/system.src.js',
          'reflect-metadata/**',
          'rxjs/**',
          'zone.js/dist/**',
          '@angular/**',
          'jquery/dist/jquery.*js',
          'bootstrap/dist/js/bootstrap.*js',
  ], {
    cwd: "node_modules/**"
  })
      .pipe(gulp.dest(destPath));
});
var tsProject = ts.createProject('app/tsconfig.json');
gulp.task('ts', function (done) {
  //var tsResult = tsProject.src()
  var tsResult = gulp.src([
          "app/*.ts"
  ])
      .pipe(ts(tsProject), undefined, ts.reporter.fullReporter());
  return tsResult.js.pipe(gulp.dest('./wwwroot/app'));
});
gulp.task('watch', ['watch.ts']);
gulp.task('watch.ts', ['ts'], function () {
  return gulp.watch('app/*.ts', ['ts']);
});
gulp.task('default', ['scriptsNStyles', 'watch']);

Open Task Runner Explorer and run the default task (you might need to refresh it first).

This will setup a watch that will look for typescript (.ts) files in the app folder of your project, compile them and then copy them into wwwroot/app.

Time to add this app folder, so right-click your project, choose Add New Folder, and name it app:

In it add the TypeScript Configuration file (tsconfig.json):

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "commonjs",
    "noEmitOnError": true,
    "noImplicitAny": false,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "moduleResolution": "node"
  },
  "exclude": [
    "node_modules",
    "typings/index",
    "typings/index.d.ts"
  ]
}

NOTE: If you don't like the compiler output to end up in your source folder you can actually use the outDir to put them somewhere else, for example:

    "outDir": "../wwwroot/app/"

Now add a new TypeScript file called app.component.ts:

NOTE: If you get compile errors, right-click the Node Dependencies folder and restore them.

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }
Add another TypeScript file called app.module.ts:
///<reference path="./../typings/globals/core-js/index.d.ts"/>
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';
@NgModule({
  imports: [BrowserModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }
Add another one called main.ts:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Almost there...
 
Open wwwroot and look for (or create) the js folder.
Add a new javascript file in this folder called systemjs.config.js:
/**
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function (global) {
  // map tells the System loader where to look for things
  var map = {
    'app': 'app', // 'dist',
    '@angular': 'lib/@angular',
    'angular2-in-memory-web-api': 'lib/angular2-in-memory-web-api',
    'rxjs': 'lib/rxjs'
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app': { main: 'main.js', defaultExtension: 'js' },
    'rxjs': { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/' + pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);
})(this);
This file differs from the one on angular.io in where it will look for things (lib instead of node_modules)...
Now add a html file under the wwwroot folder called index.html:
<html>
<head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/styles.css">
    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
    <script src="lib/core-js/client/shim.min.js"></script>
    <script src="lib/zone.js/dist/zone.js"></script>
    <script src="lib/reflect-metadata/Reflect.js"></script>
    <script src="lib/systemjs/dist/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="js/systemjs.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
</head>
<!-- 3. Display the application -->
<body>
    <my-app>Loading...</my-app>
</body>
</html>
And don't forget to add a .css style (web developers always have style right?!).
Create a css folder under wwwroot, and add a css file called styles.css:
h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}
body {
  margin: 2em;
}
 

Hit F5 to run your angular 2 web site. If all goes well you should see:

image

And if you want to learn a lot more about Angular 2, we have an excellent training on it!

Using nameof() in MVC6 razor views

C# 6 introduces the new nameof() operator, which allows you to embed the name of a class, method or property easily into your code without degrading to string-based programming... String-based programming is where you use strings, where it would be better to use code...

Razor is one of those places where there are too many strings. For example, using the new tag-helpers:

<a asp-controller="HomeController" asp-action="About">About</a>

A better, more maintainable way of doing this would be

<a asp-controller="@nameof(HomeController)" asp-action="@nameof(HomeController.About)">About</a>

You might ask why? Because, for example, renaming the About method will result in Visual Studio renaming the method in your Razor views too! And if you have a typo, the compiler will warn you. That is why!

However, out of the box MVC6 does not allow this. So I've written and published a NuGet package that allows you to use this nameof() operator in MVC6 razor views.

Simply add it to your project's dependencies in project.json:

"dependencies": {
  ...
  "U2U.NameOf": "1.0.0"
}

Add the namespace of your controllers to _ViewImports.cshtml:

@using <YourProject>.Controllers

Finally open Startup.cs and add a using statement:

using U2U;

and in the ConfigureServices method add :

services.AddMvc();
services.AddNameOf();

Now open _Layout.cshtml and change all your archors to use nameof(...):

<a asp-controller="@nameof(HomeController)" asp-action="@nameof(HomeController.Index)">

You can also use this with the old-style Html helper methods:

@Html.ActionLink("test", nameof(HomeController.Contact), nameof(HomeController))

and also in code:

Url.Action(action: nameof(HomeController.About), controller: nameof(HomeController));

I hope you like it!

Next blog post will explain how it works.