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


Recommended Free Ebook
Similar Articles