Full-Stack MVC Application with Redux

This post covers the end-to-end process (wiring MVC and React) of creating a brand new ASP.NET MVC website and adding a React component in it. We will start from scratch and end with a fully functioning component.

We can use .NET Framework, but you can instead use .NET Core if you want to be able to run your site on Linux or Mac OS. Currently .NET Core is missing some of the functionality provided by .NET Framework, so it is recommended to use .NET Framework unless you have a reason to use .NET Core specifically (eg. cross-platform support).

Start by creating a new ASP.NET Core MVC project:

  1. File → New → Project
  2. Ensure “.NET Framework 4.6” is selected in the dropdown list at the top
  3. Go to Templates → Visual C# → Web and select the “ASP.NET Core Web Application (.NET Framework)” template. 

We need to install ReactJS.NET to the newly-created project. This is accomplished using NuGet, a package manager for .NET. Right-click on your project in the Solution Explorer and select “Manage NuGet Packages”. Click the “Browse” tab, search for “React.AspNet”, and install the React.AspNet package.

We also need to modify the Startup.cs file to initialize ReactJS.NET. Open Startup.cs and perform the following changes:

At the top of the file, add:

<code class="csharp language-csharp" data-lang="csharp"><span class="k">using</span> <span class="nn">Microsoft.AspNetCore.Http</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">React.AspNet</span><span class="p">;</span>
</code>

Directly above:

<code class="csharp language-csharp" data-lang="csharp"><span class="c1">// Add framework services.</span>
<span class="n">services</span><span class="p">.</span><span class="n">AddMvc</span><span class="p">();</span>
</code>

Add:

<code class="csharp language-csharp" data-lang="csharp"><span class="n">services</span><span class="p">.</span><span class="n">AddSingleton</span><span class="p">&lt;</span><span class="n">IHttpContextAccessor</span><span class="p">,</span> <span class="n">HttpContextAccessor</span><span class="p">&gt;();</span>
<span class="n">services</span><span class="p">.</span><span class="n">AddReact</span><span class="p">();</span>
</code>

Directly above:

<code class="csharp language-csharp" data-lang="csharp"><span class="n">app</span><span class="p">.</span><span class="n">UseStaticFiles</span><span class="p">();</span>
</code>

Add:

<code class="csharp language-csharp" data-lang="csharp"><span class="c1">// Initialise ReactJS.NET. Must be before static files.</span>
<span class="n">app</span><span class="p">.</span><span class="n">UseReact</span><span class="p">(</span><span class="n">config</span> <span class="p">=&gt;</span>
<span class="p">{</span>
  <span class="c1">// If you want to use server-side rendering of React components,</span>
  <span class="c1">// add all the necessary JavaScript files here. This includes</span>
  <span class="c1">// your components as well as all of their dependencies.</span>
  <span class="c1">// See http://reactjs.net/ for more information. Example:</span>
  <span class="c1">//config</span>
  <span class="c1">//  .AddScript("~/Scripts/First.jsx")</span>
  <span class="c1">//  .AddScript("~/Scripts/Second.jsx");</span>

  <span class="c1">// If you use an external build too (for example, Babel, Webpack,</span>
  <span class="c1">// Browserify or Gulp), you can improve performance by disabling</span>
  <span class="c1">// ReactJS.NET's version of Babel and loading the pre-transpiled</span>
  <span class="c1">// scripts. Example:</span>
  <span class="c1">//config</span>
  <span class="c1">//  .SetLoadBabel(false)</span>
  <span class="c1">//  .AddScriptWithoutTransform("~/Scripts/bundle.server.js");</span>
<span class="p">});</span>
</code>

Finally, add this to Views\_ViewImports.cshtml:

<code class="csharp language-csharp" data-lang="csharp"><span class="n">@using</span> <span class="n">React</span><span class="p">.</span><span class="n">AspNet</span></code>

 

ASP.NET MVC and Redux

When we at Spoil decided to roll out our mobile app, one of the first decisions we had to make was: what language do we use? After some deliberation, the decision was made: React-Native it was going to be. Learning a new “language” or framework isn’t a huge issue. 

React-Native and Redux?

As soon as you start learning about react-native (or react), you start to understand state vs props, you know what componentDidMount does and you even understand how to properly create your components so they are re-usable. Now all of a sudden you found yourself talking about stores, reducer compositions, actions and mapping state to props.

Some Analogies

If you are coming from an MVC (or MVVC) world, you are used to models, views and controllers. However in Redux we are dealing with actions, reducers, stores and components. Trying to “translate” MVC to Redux is tricky but here is how I would do it:

Actions = Controller. Think of your actions as the controller. Whenever you want something to happen in your app (i.e. load some data, change a isLoading flag from true to false…) you will have to dispatch an action. Just like in MVC where you would have to call a controller endpoint.

Reducer = Model. Sort of. Your reducers will be in charge of holding the current state of your application (i.e. user info, information loaded from the api, items you want to display…). It will also be the part that decides what to do when an action is called. While in MVC you might have a model with the method setName(), with Redux you would have a reducer handle an action to set the name in the state.

Stores = ???. The store is Redux specific and doesn’t really have an equivalent in MVC. Not to worry though. This part is taken care off behind the scenes. The store is like a container for the state that aggregates all of the reducers. It has a method to the get the current state, and exposes ways to subscribe to the state changes (using the “connect()” method). This is what will allow you to call actions and pass them in as props to your components.

Components = Views. Components are kind of like your smart views. They display the information that they get from the state. I recommend splitting up your components into two parts. One just for the presentational part (dumb components) and one to handle all of the actions and state changes (smart components).

Moving From MVC Thinking to Redux Thinking

One of the main differences between MVC and Redux is that, while in MVC data can flow in a bidirectional manner, in Redux it strictly moves in one direction.

With Redux things work a little differently. Let’s say you have a component and you want to do something when a button gets pressed. Where do you start? 

  1. Define your Action
  2. Define your Reducer
  3. Define the Actions as a Prop in your Component
  4. Wire it up in your View

 

Copyright © All Rights Reserved - C# Learners