1️⃣ Problem: modernize ASP.NET MVC application

Let’s look at the following situation. You have an existing ASP.NET MVC application, which you need to modernize. You do not want to take a big-bang approach, but an agile one instead. You want to develop new features, using a modern framework. The following sub-requirements will emerge:

  • It should not be a complete rebuild, because a full rebuild from the UI from the application means that adding new features to the existing ASP.NET MVC application is not possible anymore because the complete rebuild (big-bang) should be finished first.
  • The rebuilding should be done step by step in an agile approach, example would be to modernize the MVC controls into modern UI controls, but in such a way that the existing functionality from the application is retained and new functionality is added using the new UI controls.

Problems

Implementing the above requirements using ASP.NET MVC poses some issues:

  1. ASP.NET MVC websites are not a SPA These are rendered server-side, sent to browser and additional JavaScript functionality is loaded in the browser.
  2. Industry favors more and more SPA apps which are using JavaScript, quickly render and responsive. Examples are Blazor (WASM), React, Angular and Vue.
  3. Modern UI frameworks are not 1:1 compatible with ASP.NET It requires access to a SPA app using a ‘Bootstrap’ process to load in the browser.
  4. Sharing data (in the UI) between SPA and ASP.NET MVC UI is not easy and straightforward.

💡 A possible solution for the above issues is ReactJS.NET. But first let me give a short recap for ReactJS.


2️⃣ React JS : a short introduction

React JS is a JavaScript library built and maintained by Facebook. React is an efficient, declarative, and flexible open-source JavaScript library for building simple, fast, and scalable front-ends of web applications.

  • React makes it easy to create interactive UIs using (and reusing components), view state and properties.
  • React uses a Virtual DOM to efficiently update and render just the right components when your data changes which make the application responsive.
  • All components implement render() function which returns html.
  • React UI component-tree is bootstrapped by calling ReactDOM.render() in JavaScript.

3️⃣ Modernize ASP.NET MVC application – Overview

When modernizing an existing ASP.NET MVC application, the required workflow could be as follows:

3.1 Original

The diagram below shows an existing ASP.NET MVC application:

3.2 One MVC Control is replaced by a React component

Using an agile approach, React is introduced and 1 MVC control is replaced.

3.3 Both MVC Controls are replaced by React components

More MVC controls on a page are replaced by React.

3.4 New features are build as React component

New functionality is implemented using a new React component.

The above diagrams show how a modernization / migration from ASP.NET MVC application to a React application can be done.


4️⃣ ReactJS.NET – Overview

ReactJS.NET makes it easier to use Facebook’s React and JSX from .NET, focusing specifically on ASP.NET MVC. It supports both ASP.NET 4 (with MVC 4 or 5), and ASP.NET Core MVC.

Using both ASP.NET MVC and React together means that:

  • The MVC Razor View rendered on server
  • The React UI components rendered in the browser

ReactJS.Net has an efficient way to include the React JavaScript libraries and call ReactDOM.Render() at the correct time during Page LifeCycle.

ReactJS.Net supports easy data sharing between the MVC page and the React components (in the GET and POST actions).


5️⃣ ReactJS.NET – How

5.1 (ReactJS side)

5.1.1 Components

ReactJS.NET supports 3 ways to create React components:

  1. On-the-fly JSX to JavaScript compilation

    1️⃣ Name your file with a .jsx extension.
    2️⃣ Link to the file via a script tag.The files will automatically be compiled to JavaScript and cached server-side. No precompilation required. Perfect for development.
  2. JSX to JavaScript compilation via minification/combination libraries

    1️⃣ Use ASP.NET Minification + Combination.
    2️⃣ Reference your JSX files and they will be included in your bundles along with your other JavaScript files.And ReactJS.NET handles all integration.

    💡If you’re a fan of Node.js-based libraries, you can use Webpack or Browserify instead, and still take advantage of ReactJS.NET’s server-side rendering.

  3. Server-side component rendering

    1️⃣ Use HTML Helper tags to render the React component server-side.
    2️⃣ Reference the required JavaScript libraries.
    3️⃣ Use ASP.NET Minification + Combination.This example code pre-renders the initial state of your React components server-side to make the initial load feel faster.

5.1.2 Components – How

To create a TypeScript React component, follow these generic high-level steps:

  • Create a TypeScript React project
  • Use WebPack to build an create “distribution”-ready JavaScript files
  • Create a React component in TypeScript, this can be a Class Component or Functional Component. Both are supported.

An example React component could look like this:

1️⃣ Define the input properties which are passed from the MVC side to the React component.
2️⃣ Define the component (in this example it’s a functional Popup component).
3️⃣ React hook to conditionally render the component.
4️⃣ The code to render the Popup component on the screen.

5.2 MVC .NET side

5.2.1 Config

In your ASP.NET MVC application, you need to configure the following code to be able to register, integrate and use ReactJS.Net:

1️⃣ Define a PreApplicationStartMethod which allows you to have code run way early in the ASP.NET pipeline as an application starts up. (Even before Application_Start). The Configure method is passed to indicate that this method should be run.
2️⃣ The Configure-method.
3️⃣ Add all JavaScript (distribution) files which contain the complete React application.
4️⃣ Set the default .NET JavaScript Engine. See next chapter for an explication.

5.2.2 JavaScript Engines

JavaScript Engines can be used to compile and execute JavaScript code.

There are many available, see the list below.

Note that for my example code, I used the V8-engine.

5.2.3 Page (design)

Create a Razor Page and add the React component(s) using the static Html helper methods to define the React component.

💡 Note that the name of the component (in this example it’s PopupComponent) should be exact like the React component you have designed in chapter 5.1.2. This runtime check is done by the JavaScript Engine which interprets the provides (distribution) JavaScript files.

💡 Note that it’s perfectly valid to define the same React component multiple times on the same page. In this example a different text is provided from the .NET side to the React side. React.Net takes care of passing these properties correctly to the React component.

5.2.4 Page (source)

When looking at the source-code from the rendered page, there are two important parts.

Part 1

This code block shows how React.Net rendered the required (unique) div where the React component will be rendered. In addition also the HTML code emitted by the React component will be added here.

🅰️ This is the first PopupComponent which has a unique id.
🅱️ This is the second PopupComponent which has a unique id.

Part 2

This code block shows how React.Net rendered the additional JavaScript which is needed to correctly link the (unique) div to the React component. You can also see how the property-calues are passed from .NET to React.

1️⃣ The required (distribution) JavaScripts are included here.
2️⃣ The additional script-section added by React.Net.


5.3 .NET (Core)

React.Net can also be used in combination with a .NET (Core) project, the only difference is the way React.Net is configured in the pipeline. For an example on how to do this, see the code below:

var builder = WebApplication.CreateBuilder(args);

// 1. Configure the ChakraCoreJsEngine
builder.Services.AddJsEngineSwitcher(options => options.DefaultEngineName = ChakraCoreJsEngine.EngineName)
    .AddChakraCore();

// 2. AddReact
builder.Services.AddReact();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

// 3. Initialise ReactJS.NET. Must be before static files.
app.UseReact(config =>
{
    config
        // .SetLoadBabel(false)
        .AddScriptWithoutTransform("~/js/dist/vendor.js")
        .AddScriptWithoutTransform("~/js/dist/runtime.js")
        .AddScriptWithoutTransform("~/js/dist/components.js")
        .SetJsonSerializerSettings(new JsonSerializerSettings
        {
            StringEscapeHandling = StringEscapeHandling.EscapeHtml
        })
        ;
});


app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

See also the official documentation.


💻 Demo

For a demo-project, see my React.Net.Examples.


💡 Conclusion

This blog post explains how to modernize (not rebuild) an existing ASP.NET MVC by migrating the MVC Controls step by step to ReactJS-components by using React.Net. This approach enables a more agile approach when modernizing.


❔ Feedback or questions

Do you have any feedback or questions regarding this, or one of my other blogs? Feel free to contact me!


📚 Additional resources