Open Microsoft Visual Studio, Create new project, ASP.NET Core Web API, Project Name: ProductsApi
Right click on ProductsApi->Add->New Folder->Models,
Right click on ProductsApi->Add->New Folder->Data,
Right click on Models->Add->Class->name it Products.cs
Delete the default code and add the following code
// This namespace groups related classes together.
// “ProductsApi.Models” means this class belongs to the Models folder
// inside the ProductsApi project.
namespace ProductsApi.Models
{
// This is a public class named Product.
// A class is like a blueprint or template for creating objects.
// This Product class represents a product in our database.
public class Product
{
// This property represents the unique ID of the product.
// “int” means integer number.
// { get; set; } allows reading (get) and writing (set) the value.
// In database, this usually becomes the Primary Key.
public int Id { get; set; }
// This property stores the Name of the product.
// “string” means text.
// Example: “Laptop”, “Mouse”, “Keyboard”
public string Name { get; set; }
// This property stores the Price of the product.
// “decimal” is used for money values because it gives high precision.
// Example: 1500.50
public decimal Price { get; set; }
// This property stores how many items are available in stock.
// “int” means whole number.
// Example: 10, 25, 100
public int Stock { get; set; }
}
}
Program.cs Code:
// This allows us to use Entity Framework Core features
// (like UseSqlServer, DbContext, etc.)
using Microsoft.EntityFrameworkCore;
// This allows us to use AppDbContext class
// which is inside the Data folder of our project
using ProductsApi.Data;
// This creates a WebApplication builder object.
// It prepares configuration, services, logging, etc.
var builder = WebApplication.CreateBuilder(args);
// ----------------------
// Add services to the container
// ----------------------
// Controllers (API endpoints)
builder.Services.AddControllers();
// Swagger (API documentation/testing)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// DbContext (EF Core + SQL Server)
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")
)
);
//Add Cors
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowReact", policy =>
{
policy
.WithOrigins("http://localhost:5173")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
// Build the application
var app = builder.Build();
// ----------------------
// Configure the HTTP request pipeline (Middleware)
// ----------------------
// Use Swagger only in Development environment (recommended)
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// Redirect HTTP requests to HTTPS automatically
app.UseHttpsRedirection();
// Enables CORS middleware
app.UseCors("AllowReact");
// Enables authorization middleware.
// (Even if we are not using authentication yet)
app.UseAuthorization();
// Maps controller routes (like api/products)
app.MapControllers();
// Starts the application
app.Run();
Right click on Data->Add->Class->AppDbContext.cs
// This allows us to use Entity Framework Core classes // like DbContext, DbSet, etc. using Microsoft.EntityFrameworkCore;// This allows us to use the Product model class // which is inside the Models folder. using ProductsApi.Models;// This namespace represents the Data layer of our project. // Usually, DbContext and database-related classes stay here. namespace ProductsApi.Data { // AppDbContext inherits from DbContext. // DbContext is the main class of Entity Framework Core // that manages database connection and database tables. public class AppDbContext : DbContext { // This is the constructor of AppDbContext. // It receives configuration options from Program.cs. // These options contain the connection string and database provider info. public AppDbContext(DbContextOptions<AppDbContext> options) // This passes the options to the base class (DbContext). // Without this, EF Core cannot configure the database properly. : base(options) { }// DbSet<Product> represents a table in the database. // “Products” will become the table name in SQL Server. // Each Product object represents one row in the table. public DbSet<Product> Products { get; set; } } }
Right click on Controllers->Right click on WeatherForecastControllers.cs and delete it
Right click on Controllers->Add->Class->ProductsController.cs
// This allows us to use ASP.NET Core MVC features
// like ControllerBase, IActionResult, ApiController, HttpGet, HttpPost, etc.
using Microsoft.AspNetCore.Mvc;
// This allows us to use AppDbContext (database connection class)
using ProductsApi.Data;
// This allows us to use Product model
using ProductsApi.Models;
// This namespace contains all API controllers
namespace ProductsApi.Controllers
{
// [ApiController] enables automatic validation,
// better error responses, and API-specific behaviors
[ApiController]
// Defines the route pattern for this controller.
// [controller] automatically becomes "products"
// So final route becomes: api/products
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
// Private readonly field to hold database context.
// "readonly" means it cannot be changed after initialization.
private readonly AppDbContext _context;
// Constructor with Dependency Injection.
// ASP.NET automatically provides AppDbContext
// because we registered it in Program.cs.
public ProductsController(AppDbContext context)
{
// Assign injected context to local variable
_context = context;
}
// ---------------------------------------
// GET: api/products
// ---------------------------------------
// This attribute makes this method respond to HTTP GET requests
[HttpGet]
public IActionResult GetAll()
{
// Fetch all products from database.
// ToList() executes SQL query and returns a list.
var products = _context.Products.ToList();
// Returns HTTP 200 OK with product list in JSON format
return Ok(products);
}
// ---------------------------------------
// POST: api/products
// ---------------------------------------
// This attribute makes this method respond to HTTP POST requests
[HttpPost]
public IActionResult Create(Product product)
{
// Adds new product to EF tracking
// (Not saved to database yet)
_context.Products.Add(product);
// Saves changes to database (Executes INSERT SQL)
_context.SaveChanges();
// Returns HTTP 200 OK with created product
return Ok(product);
}
}
}
appsettings.json{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=ProductsDb;Trusted_Connection=True;TrustServerCertificate=True;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}Open SQL Server Management Studio and Click connect, Create New Database ProductsDb and click ok
Click on Tools Nuget Package Manager->Manage Nuget Packages for Solutions
Install Packages->
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore
Swashbuckle.AspNetCore
Go to Tools->Nuget Package Manager->PM->Add-Migration InitialCreate
Build Start->Build Scucced->Click https at the top then copy the https://localhost:7235
https://localhost:7235/swagger
Frontend development with Reactjs and Tailwindcss
Open Visual Studio Code
Drag products-ui folder inside VSCode
npm create vite@latest .
click React, Javascripts, ok ok
npm run dev
npm install -D tailwindcss@3 postcss autoprefixer
npx tailwindcss init -p
inside tailwind.config.js:
/** @type {import(‘tailwindcss’).Config} / export default { content: [ “./index.html”, “./src//.{js,ts,jsx,tsx}”,
],
theme: {
extend: {},
},
plugins: [],
}
inside index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Create: src/api.js
import axios from 'axios';
export const api = axios.create({
baseURL: 'https://localhost:7235',
});
npm i axios
Replace src/App.jsx with:
import { useEffect, useState } from “react”;
import { api } from “./api”;
export default function App() {
const [products, setProducts] = useState([]);
const [name, setName] = useState(“”);
const [price, setPrice] = useState(“”);
async function loadProducts() {
const res = await api.get(“/api/products”);
setProducts(res.data);
}
async function createProduct(e) {
e.preventDefault();
const newProduct = {
name,
price: Number(price),
};
await api.post(“/api/products”, newProduct);
setName(“”);
setPrice(“”);
loadProducts();
}
useEffect(() => {
loadProducts();
}, []);
return (
<div className=”min-h-screen bg-slate-100 p-6″>
<div className=”mx-auto max-w-3xl space-y-6″>
<h1 className=”text-2xl font-bold”>Products</h1>
{/* Create Product Form */}
<form
onSubmit={createProduct}
className=”rounded-lg bg-white p-4 shadow space-y-3″
>
<div>
<label className=”block text-sm font-medium”>Product Name</label>
<input
className=”mt-1 w-full rounded border p-2″
value={name}
onChange={(e) => setName(e.target.value)}
placeholder=”e.g. Mouse”
required
/>
</div>
<div>
<label className=”block text-sm font-medium”>Price</label>
<input
className=”mt-1 w-full rounded border p-2″
value={price}
onChange={(e) => setPrice(e.target.value)}
placeholder=”e.g. 350″
type=”number”
required
/>
</div>
<button className=”rounded bg-black px-4 py-2 text-white hover:opacity-90″>
Add Product
</button>
</form>
{/* Products Table */}
<div className=”rounded-lg bg-white p-4 shadow”>
<table className=”w-full border-collapse”>
<thead>
<tr className=”border-b text-left”>
<th className=”py-2″>Id</th>
<th>Name</th>
<th className=”text-right”>Price</th>
</tr>
</thead>
<tbody>
{products.map((p) => (
<tr key={p.id} className=”border-b”>
<td className=”py-2″>{p.id}</td>
<td>{p.name}</td>
<td className=”text-right”>{p.price}</td>
</tr>
))}
{products.length === 0 && (
<tr>
<td className=”py-3 text-slate-500″ colSpan={3}>
No products found.
</td>
</tr>
)}
</tbody>
</table>
</div>
<p className=”text-sm text-slate-600″>
Make sure your API is running and CORS is enabled.
</p>
</div>
</div>
);
}
npm run dev
keep https://localhost:7235/swagger/index.html running