A React Front-end with a .NET Web API Back-end Application

Introduction

React, the JavaScript library for building interactive and attractive UIs, is very famous these days. There are many articles on learning React and creating a React application. However, today, I would like to showcase a simple application skeleton in which we create a simple React front-end UI and connect it to a .NET core Web API to get the data.

React front-end application

I have created a simple React application using Vite. I would recommend you look into this framework for building JavaScript framework front-end applications here.

After creating the initial application using React and TypeScript, you can update/create the components as below. Bootstrap was added for styling. I am using Visual Studio Code for designing and developing the application.

//Main.tsximport React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'
import './index.css'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <BrowserRouter>
    <App />
    </BrowserRouter>
  </React.StrictMode>,
)
//App.tsximport { Link, Route, Routes } from 'react-router-dom'
import Home from './components/Home'
import Employees from './components/Employees'
import AddEmployee from './components/AddEmployee'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'

const App = () => {
  return (
    <>

      <nav className="navbar bg-body-tertiary">
        <div>
        <a className="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                  Main Menu
                </a>
                <ul className="dropdown-menu">
                  <li><a className="dropdown-item" href="/">Home</a></li>
                  <li><a className="dropdown-item" href="/employees">Employees</a></li>
                  <li><a className="dropdown-item" href="/addemployee">Add Employee</a></li>
                </ul>
        </div>
      </nav>

      <p />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/employees" element={<Employees />} />
        <Route path="/addemployee" element={<AddEmployee />} />
        <Route />
      </Routes>
    </>
)}

export default App
//Home.tsx

const Home = () => {
    return <h1 className="text-center">Home</h1>
};
export default Home;
//Employees.tsx

import axios from 'axios';
import { useEffect, useState } from "react";
import url from "../misc/fixed";

interface Employee{
  id: number,
  name: string,
  age:number,
  counter:number
}

const Employees = () => {

    const [employees, setEmployees] = useState<Employee[]>([]);
    
    useEffect(() => {
      getEmployees();
    },[])

    const getEmployees = () => {
      axios.get<Employee[]>(url)
      .then(res => setEmployees(res.data));
    }

    const onDelete = (id: number) =>
    {
      axios.delete(url + `/${id}`)
      .then(res=> console.log(res.data))  // getEmployees()
      .catch(err=> console.log(err));
      setEmployees(employees.filter((e) => e.id != id)); // This is temporary
    }

    if (employees.length == 0) return (
      <>
      <h1 className="text-center">Employees</h1>
      <p/>
      <h3>There are no employees</h3>
      </>
    );

    return (
    <>
    <h1 className="text-center">Employees</h1>
    <p/>
    <div className="container text-center">
    <div className="row">
    <div className="col" style={{backgroundColor: "darkblue", color:"white"}}>
      Employee Id
    </div>
    <div className="col" style={{backgroundColor: "darkblue", color:"white"}}>
      Employee Name
    </div>
    <div className="col" style={{backgroundColor: "darkblue", color:"white"}}>
      Employee age
    </div>
    <div className="col" style={{backgroundColor: "darkblue", color:"white"}}>
    </div>
    </div>

    {employees.map((employee)=> (
        <div className="row" key={employee.id}>
        <div className= {employee.counter%2 == 0 ? "col p-3 mb-2 bg-info text-dark" : "col p-3 mb-2 bg-light text-dark"}>
          {employee.id}
        </div>
        <div className={employee.counter%2 == 0 ? "col p-3 mb-2 bg-info text-dark" : "col p-3 mb-2 bg-light text-dark"}>
        {employee.name}
        </div>
        <div className={employee.counter%2 == 0 ? "col p-3 mb-2 bg-info text-dark" : "col p-3 mb-2 bg-light text-dark"}>
        {employee.age}
        </div>
        <div className={employee.counter%2 == 0 ? "col p-3 mb-2 bg-info text-dark" : "col p-3 mb-2 bg-light text-dark"}>
        <button className="btn btn-outline-danger" onClick={() => onDelete(employee.id)}>
         Delete
        </button>
        </div>
        </div>
        ))}    
    </div>
    </>
    )};

export default Employees;
//AddEmployee.tsx

import axios from 'axios';
import { FormEvent, useEffect, useRef, useState } from "react";
import url from "../misc/fixed";
import { CAlert, CButton } from '@coreui/bootstrap-react';

const AddEmployee = () => {

    const [id, setId] = useState("");
    const [name, setName] = useState("");
    const [age, setAge] = useState("");

    function handleSubmit(event: FormEvent<HTMLFormElement>): void {
        event.preventDefault(); 

        const emp = { id:id, name:name, age:age, counter:0 }
        axios.post(url, emp)
          .then(res=> {console.log(res.data); setVisible(true);}) 
          .catch(err=> console.log(err));
    }

    const resetForm = () => {
        setVisible(false);
        setId("");
        setName("");
        setAge("");
    } 

    const [visible, setVisible] = useState(false)

    return(
        <>
        <h1 className="text-center">Add employee</h1>
        <p/>

        <CAlert color="success" dismissible visible={visible} onClose={() => resetForm()}>Employee saved!</CAlert>
        
        <form onSubmit={handleSubmit}>    
        <div className="mb-3" style={{width: "200px", padding: "10px"}}>
        <label htmlFor="id" className="form-label">
          Employee Id:
        </label>
        <input id="id" type="text" className="form-control" onChange={(event) => setId(event.target.value)} value={id} />
        </div>
        <div className="mb-3" style={{width: "200px", padding: "10px"}}>
        <label htmlFor="name" className="form-label">
          Employee name:
        </label>
        <input id="id" type="name" className="form-control" onChange={(event) => setName(event.target.value)} value={name} />
        </div>
        <div className="mb-3" style={{width: "200px", padding: "10px"}}>
        <label htmlFor="age" className="form-label">
          Employee age:
        </label>
        <input id="age" type="number" className="form-control" onChange={(event) => setAge(event.target.value)} value={age} />
        </div>
        <div className="mb-3" style={{width: "200px", padding: "10px"}}>
        <button className="btn btn-primary">Save Employee</button>
        </div>
        </form>
        </>
    );

}

export default AddEmployee;
//fixed.ts
const url = 'https://localhost:7201/api/Employee' as const;
xport default url

The package.json file is below.{
  "name": "employee-demo",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@coreui/bootstrap-react": "^1.0.0-beta.0",
    "axios": "^1.4.0",
    "bootstrap": "^5.3.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.11.2"
  },
  "devDependencies": {
    "@types/bootstrap": "^5.2.6",
    "@types/react": "^18.0.27",
    "@types/react-dom": "^18.0.10",
    "@vitejs/plugin-react": "^3.1.0",
    "typescript": "^4.9.3",
    "vite": "^4.1.0"
  }
}

The layout of the project is as below.

A React Front-end with a .NET Web API Back-end Application

.NET Core Web API back-end application

The back-end application is a simple .NET Core Web API application. The code is as below.

EmployeeController.cs

using Microsoft.AspNetCore.Mvc;

namespace EmployeesBackEndApp.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeController : ControllerBase
    {
        private readonly ILogger<EmployeeController> _logger;
        private List<Employee> employees;
        public EmployeeController(ILogger<EmployeeController> logger)
        {
            _logger = logger;
            employees = PopulateEmployees();
        }

        [HttpGet(Name = "GetEmployees")]
        public IEnumerable<Employee> Get()
        {
            return employees;
        }

        [HttpDelete("{id}", Name = "DeleteEmployee")]
        public int Delete([FromRoute] int id)
        {
            var employee = employees.FirstOrDefault(x => x.id == id);
            if (employee != null) employees.Remove(employee);
            return id;
        }

        [HttpPost]
        public int AddEmployee([FromBody] Employee employee)
        {
            employees.Add(employee);
            return employee.id;
        }

        List<Employee> PopulateEmployees()
        {
            return new List<Employee>
            {
                new Employee
                {
                    id = 100,
                    name = "Munib Butt",
                    age = 52,
                    counter = 1
                },
                new Employee
                {
                    id = 200,
                    name = "John Doe",
                    age = 25,
                    counter = 2
                },
                new Employee
                {
                    id = 300,
                    name = "Mike Doe",
                    age = 30,
                    counter = 3
                },
                new Employee
                {
                    id = 400,
                    name = "John Smith",
                    age = 35,
                    counter = 4
                }
            };
        }
    }

    public class Employee
    {
        public int id { get; set; }
        public string? name { get; set; }
        public int age { get; set; }
        public int counter { get; set; }
    }
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseCors(builder => builder
    .AllowAnyOrigin()
    .AllowAnyMethod()
    .AllowAnyHeader());

app.UseAuthorization();

app.MapControllers();

app.Run();

The complete project looks like the below in Visual Studio 2022.

A React Front-end with a .NET Web API Back-end Application

Running the applications

We first run the back-end application. Then, we run the React application.

A React Front-end with a .NET Web API Back-end Application

A React Front-end with a .NET Web API Back-end Application

A React Front-end with a .NET Web API Back-end Application

Summary

Today, I presented a simple application skeleton with a React front-end and .NET Core Web API backend. This is a simple example that shows how we can start an application using these technologies in the application design architecture. It can be expanded according to your application needs.

Github