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.
.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.
Running the applications
We first run the back-end application. Then, we run the React 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