Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Implement CRUD Forms with React and ASP.NET Core - Part 2

0.00/5 (No votes)
8 Nov 2017 1  
In this tutorial, I'll be building a high performance ASP.NET Core React.js Single Page Application that implements CRUD forms with validation without using Redux or JQuery. This is part two of a three part series.

Introduction

In this part of our tutorial, we'll be building our high performance ASP.NET Core React.js components without using Redux or JQuery. If you haven't completed Part 1 of this tutuorial, you'll want to do that first and then return to this page. We'll start by creating our client-side models.

Client-side Models

Client-side what? Since our React components will need access to our models, we will need client side models as well as the server-side models we created earlier. Fortunately, our client-side models will be much simpler since TypeScript has just a few simple types and we will not need any attributes. Just like our server-side models, we will have three classes: Actor, Movie, and MovieActor.

Start by expanding the ClientApp folder, then right-click on the ClientApp folder, select Add, then New Item...(figure 1). From the Templates box on the left, select ASP.NET Core, then Web, then Scripts. Select TypeScript File from the middle box, and enter the name models.ts (figure 1).

Add New Item dialog

Figure 1

Copy and paste the three models shown below (figure 2):

export class Actor{
	Id: number;
	Name: string;
	Gender: string;
	Age: number;
	Picture: string;
}
export class Movie{
	Id: number;
	Title: string;
	Director: string;
	DateReleased: string;
	ReleasedBy: string;
	Rating: string;
	Genre: string;
	GrossRevenue: number;
}
export class MovieActor{
	MovieId: number;
	ActorId: number;
}
Figure 2

The Actor Component

Now let's create the Actor React.js component. As I mentioned in Part 1, each of our components will live in their own folder. So start by creating a folder under ClientApp/Components called Actor. Then right-click the Actor folder, select Add, then New Item... From the left-side of the Add New Item dialog box, select ASP.NET Core, then Web, then Scripts (fig 3). Then select TypeScript JSX file from the middle box and name the file: Index.tsx.

Add New Item dialog

Figure 3

TypeScript JSX files are what we use to create React components.

Imports

Import statements in ES6 (the current version of JavaScript) are similar to using statements in C# - they allow us to reference other script modules. We'll need to reference our client-side models and a few other things so let's add some import statements. Our first three imports include: a reference to React, a reference to React Router, and a reference to our client models. Copy these three import statements as shown below (fig 4).

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import * as models from '../../models'
Figure 4

React components are stateful and are called 'controlled'. In React, you only ever modify the state and React takes care of the rendering. We don't ever touch the DOM, which is why we don't need JQuery. In fact, manipulating the DOM is potentially problematic since you can corrupt your component's state. It's a very clean architecture but if you're a seasoned developer, you have to fight the urge to manipulate the DOM directly. We will use an Interface to define the state for the Actor component. Just below the import statements you just copied, copy the following interface (figure 5).

interface ActorState {
	actor: models.Actor[]
    loading: boolean
}
Figure 5

Let's continue. Our component will be usable anywhere in our application (and reusable by other applications), so the class declaration must start with 'export' and will also extend Rect.Component. We'll start with the constructor, which will initialize the state of the component and fetch the data for the view. Copy the code shown below (figure 6):

export class Actors extends React.Component<routecomponentprops<{}>, ActorState> {
    constructor(props) {
        super(props);
        this.state = {
            actor: [],
            loading: true
        };
        fetch('api/actor/index')
			.then(response => response.json() as Promise<models.actor[]>)
            .then(data => {
                this.setState({
                    actor: data,
                    loading: false,
                });
            });
    }
Figure 6

The magic of React components happens in the render() method. Whenever you change the state of your component by setting one of the values, React will re-render your component. So let's write our render method as shown below (fig 7). You may have noticed that we've inserted the variable: {contents} in the returned markup. This simply allows us to breakup the markup into more manageable pieces, which will become more important as our components get more complicated.

render() method

Figure 7

Lastly, we just need to write our renderTable() method. It's a fairly basic HTML table, but you'll want to take note of a couple of things. The JavaScript .map() method is used to iterate our data, which is passed to our method as the parameter: actor. Also React highly recommends adding a unique 'key' to markup that takes the form of tables or ul and ol that can potentially contain many entries. This allows React to optimize how it re-renders your component, i.e., in our example, re-rendering only the rows that have changed. Go ahead and type the markup shown below (figure 8).

renderTable() method

Figure 8

That completes our component. Next, we'll move on to our controller.

The Controller

As I mentioned in Part 1, our controller will be an ASP.NET Core WebAPI controller. It will return JSON, which means we can leverage it to also serve native mobile applications. Let's get started.

Right-click on the Controllers folder and select Add, then Controller. If a popup entitled 'Add dependencies to enable scaffolding' appears, select Minimal Dependencies and wait for Visual Studio to install some scaffolding packages, then try again. From the Add Scaffold popup, select API Controller with Actions using Entityframework. Then from the next popup, select Actor for the Model, and AppDbContext for the Data context (figure 9). Note if your project contains any compiler errors, the operation will fail and you will need to address those first.

Add Controller dialog

Figure 9

We're going to make a small change to the controller. We're going to rename the GetActors() method to Index() for the sake of keeping with old MVC conventions (indulge me on this one). Also, we're adding the [HttpGet("[action]")] attribute to allow us to call the method using the action name (Index). Go ahead and make those two changes now (figure 9.1).

[Produces("application/json")]
[Route("api/Actors")]
public class ActorController : Controller
{
    private readonly AppDbContext _context;

    public ActorsController(AppDbContext context)
    {
        _context = context;
    }

    //[HttpGet]
    //public IEnumerable<actor><Actor> GetActors()
    [HttpGet("[action]")]
    public IEnumrable<Actor> Index()
    {
        return _context.Actors;
    }
Figure 9.1

Routing

Routing in our React Single Page Application is handled by the react-router component. We need to tell it about our new component by adding entries to the ClientApp/routes.tsx and ClientApp/components/navmenu.tsx files. Make the modifications shown below (figures 10 and 11).

routes.tsx

Figure 10

NavMenu.tsx

Figure 11

At this point, we can run our application and access our Actor component (aka view). You won't have any data in your view, but if you'd like to see data at this juncture, you can simply add it to the database using SQL Management Studio.

Actor component rendered

Figure 12

That concludes Part 2 of this tutorial. Stay with us. In Part 3, we'll be making the magic happen by adding our Create, Edit, Details and Delete methods!

How to Implement CRUD forms with React and ASP.NET Core - Part 1

History

  • 11/8/2017: Initial article

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here