Getting started with React, TypeScript and ASP.NET 5 MVC 6

Since I had trouble finding a good guide on how to get started with React using TypeScript and the brand new ASP.NET 5 MVC 6 I decided to write one my self. As a bonus I’ll show you how to set up Webpack to neatly bundle the React application.

Here’s what you’ll need to have installed before we get going:

The source code of this walkthrough is available in GitHub so if you’re having any trouble just grab the example application from this repository.

Create a new ASP.NET 5 MVC 6 project

Awesome, let’s get started! First create a new ASP.NET Web Application project. In the next dialog choose Empty template under ASP.NET 5 Templates. This is to keep things simple and we’ll only be adding add the stuff we actually need. If you wanted you could instead go with the full-blown Web Application template too.

Install ReactJS.NET

Next you’ll need to modify your project.json file so open it up. To work with React in .NET we’ll be using a library called ReactJS.NET. It will allow us to do server side (or isomorphic) rendering which is cool but more on that later.

Before installing ReactJS.NET we’ll need to remove "dnxcore50": { } line from project.json to make it work. Then add "React.AspNet": "2.1.2" and "Microsoft.AspNet.Mvc": "6.0.0-rc1-final" under dependencies and save the file. Both ASP.NET MVC 6 and ReactJS.NET should get immediately installed.

Your project.json should now look something like this:

{
  "version": "1.0.0-*",
  "compilationOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "React.AspNet": "2.1.2"
  },

  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel"
  },

  "frameworks": {
    "dnx451": { }
  },

  "exclude": [
    "wwwroot",
    "node_modules"
  ],
  "publishExclude": [
    "**.user",
    "**.vspscc"
  ]
}

Hello World React-component

The fun starts here! Create a new folder called app under your project. This is where we’ll be hosting all our React components. Right-click that folder and add a new item. Search for a TypeScript JSX file template and name your file HelloWorld.tsx. Add the following lines.

/// <reference path="../../../typings/main/ambient/react/index.d.ts" />
import React = require('react');

// A '.tsx' file enables JSX support in the TypeScript compiler, 
// for more information see the following page on the TypeScript wiki:
// https://github.com/Microsoft/TypeScript/wiki/JSX

interface HelloWorldProps extends React.Props<any> {
    name: string;
}

class HelloMessage extends React.Component<HelloWorldProps, {}> {
    render() {
        return <div>Hello {this.props.name}</div>;
    }
}

export = HelloMessage;

It’s a very simple React component that just renders a div with a message including the name that can be passed as a property. There are plenty of tutorials about creating React components so I won’t go into the detail here.

You’ll see that the react.d.ts cannot be resolved. To fix this you’ll need to run typings install react --ambient --save in the Package Manager console to install the TypeScript definitions for react. Visual Studio will still complain about the --module flag that must be provied. To fix this add a tsconfig.json in the app folder with the following content:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "jsx": "preserve"
  }
}

This file will instruct TypeScript to use CommonJS modules, target ES6 and preserve the generated JSX-files. Now go back to HelloWorld.tsx and save it - you’ll see a corresponding HelloWorld.jsx get generated.

Note. If the JSX isn’t being generated make sure that you have enabled TypeScript compilation in Visual Studio. To do this check the Automatically compile TypeScript files which are not part of the project under Tools -> Options -> TypeScript -> Project -> General in Visual Studio.

Setup Webpack

To neatly bundle the React components we’ll be using Webpack although you could use any other module bundler as well. You should have installed Webpack already but if you haven’t check out the beginning of this post on how to do it.

In the app folder create index.js:

module.exports = {
    // All the components you'd like to render server-side
    HelloMessage: require('./HelloWorld')
};

This will be used to tell Webpack which components to bundle together for server and client side rendering. Right now we only have the HelloWorld component.

Next in your wwwroot folder add two files called client.js and server.js. They both share the same content for this project:

// All JavaScript in here will be loaded client/server -side.
// Expose components globally so ReactJS.NET can use them
var Components = require('expose?Components!./../app');

We’re almost done! The last thing that’s left is a Webpack configuration file. Create webpack.config.js under your project:

var path = require('path');

module.exports = {
    context: path.join(__dirname, 'wwwroot'),
    entry: {
        server: './server',
        client: './client'
    },
    output: {
        path: path.join(__dirname, 'wwwroot/build'),
        filename: '[name].bundle.js'
    },
    module: {
        loaders: [
            // Transform JSX in .jsx files
            { test: /\.jsx$/, loader: 'jsx-loader?harmony' }
        ],
    },
    resolve: {
        // Allow require('./blah') to require blah.jsx
        extensions: ['', '.js', '.jsx']
    },
    externals: {
        // Use external version of React (from CDN for client-side, or
        // bundled with ReactJS.NET for server-side)
        react: 'React'
    }
};

Webpack will need some additional modules to do the bundling. Right-click the project and select “Add item”. In the dialog choose NPM Configuration file and name it package.json:

{
    "version": "1.0.0",
    "name": "ASP.NET",
    "private": true,
    "devDependencies": {
        "webpack": "1.12.9",
        "expose-loader": "0.7.1",
        "jsx-loader": "0.13.2"
    }
}

Once again saving the file will execute NPM and install the three packages.

Finally open command prompt and browse to the project’s folder (where webpack.config.js is located). Then type webpack, press enter and Webpack should beautifully build two JavaScript bundles under wwwroot/build. Of these client.bundle.js should be included client side and server.bundle.js should be included server side… easy huh!

Remember to run webpack each time you have modified your React components or add this step to your build process.

Add a controller and a view

Let’s next do the obvious thing of creating a controller and a view so that we can host our fancy React component somewhere. Create a folder called Controllers under the project and add a new controller called HomeController under the folder. The controller should have only one GET Index method like so:

using Microsoft.AspNet.Mvc;

namespace React.MVC6.Sample.Controllers
{
    public class HomeController : Controller
    {
        // GET: /<controller>/
        public IActionResult Index()
        {
            return View();
        }
    }
}

After that add a folder called Views under the project. Under Views add a new folder called Shared. Create a layout file called _Layout.cshtml there with the following content:

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Next let’s add a few defaults for our views. In the Views folder add a new file called _ViewImports.cshtml with just the following content. This will ensure that ReactJS.NET is by default available in all our views.

@using React.AspNet

Create another file called _ViewStart.cshtml under Views folder with this content:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

Finally create a new folder called Home under Views and create a file called Index.cshtml in there. Place the following in there to render your React component with initial data:

@{
    ViewBag.Title = "Index";
}

<h1>Hello World</h1>

@Html.React("Components.HelloMessage", new { name = "Sam" })

<script src="https://fb.me/react-0.14.0.min.js"></script>
<script src="https://fb.me/react-dom-0.14.0.min.js"></script>
<script src="@Url.Content("/build/client.bundle.js")"></script>

@Html.ReactInitJavaScript()

Including the javascripts in the view like this isn’t very pretty but you’ll get the idea. The name that we pass to the component could as well come from a model passed down from the controller. Doing isomorphic server side rendering couldn’t be any easier!

Configure the Web Application

Finally we’ll need to make sure that ASP.NET MVC 6 and React get loaded properly when the application starts up. So open up your startup.cs file and replace the contents with this:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using React.AspNet;

namespace React.MVC6.Sample
{
    public class Startup
    {
        // Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddReact(); // Add React to the IoC container
            services.AddMvc();
        }

        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            app.UseIISPlatformHandler();

            // Initialise ReactJS.NET. Must be before static files.
            app.UseReact(config =>
            {
                config
                    .SetReuseJavaScriptEngines(true)
                    .AddScriptWithoutTransform("~/build/server.bundle.js");
            });

            app.UseStaticFiles(new StaticFileOptions
            {
                ServeUnknownFileTypes = true
            });

            app.UseMvc(r =>
            {
                r.MapRoute(
                    name: "default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" }
                );
            });
        }

        // Entry point for the application.
        public static void Main(string[] args) => WebApplication.Run<Startup>(args);
    }
}

That’s it!

Just run your project and you should see the Hello World page rendered! It has been rendered server side meaning that your users don’t have to wait for all the JavaScript to load and it’s instantly indexable by Google and other search engines too. Now go expirement with React and create some more components that include some client side interactions. It should all work out-of-the-box - just remember to include all components in index.js and run webpack after changes.

The source code of this walkthrough is available in GitHub so if you’re having any trouble just grab the example application from this repository.