API Integration — Fetching from .NET Web API
Level: Beginner
- Using fetch API to call .NET Web API endpoints
- Axios as alternative to fetch with better DX
- async/await for clean async code
- Error handling for network and API failures
- Authentication headers (JWT, bearer tokens)
- Loading and error states while fetching
- Pagination and filtering API responses
- Integrating with SMS student, fee, attendance APIs
Why This Matters
API Integration — Fetching from .NET Web API is part of building maintainable React applications. You will use it when creating student dashboards, forms, tables, API-connected screens, routing flows, and reusable UI components.
React frontends need backend data. You've built the ASP.NET Web API; now consume it from React.
The Problem
Beginners often write React code that works for a small demo but becomes difficult when data, forms, API calls, and reusable components grow. This lesson explains API Integration — Fetching from .NET Web API in a way that helps you build predictable UI for real .NET Web API projects.
Basic Fetch Pattern
function StudentList() {
const [students, setStudents] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchStudents = async () => {
try {
const response = await fetch('http://localhost:5000/api/students');
if (!response.ok) throw new Error('Failed to fetch');
const data = await response.json();
setStudents(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchStudents();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{students.map(s => (
<li key={s.id}>{s.name}</li>
))}
</ul>
);
}
GET Request
// Fetch one student
useEffect(() => {
fetch(`http://localhost:5000/api/students/${studentId}`)
.then(r => r.json())
.then(data => setStudent(data));
}, [studentId]);
// With query parameters
const params = new URLSearchParams({
className: '10',
status: 'Active'
});
fetch(`http://localhost:5000/api/students?${params}`)
.then(r => r.json())
.then(data => setStudents(data));
POST Request (Create)
function CreateStudent() {
const [formData, setFormData] = useState({
name: '',
email: '',
className: '10'
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('http://localhost:5000/api/students', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
if (!response.ok) throw new Error('Failed to create');
const newStudent = await response.json();
console.log('Created:', newStudent);
setFormData({ name: '', email: '', className: '10' });
} catch (err) {
console.error(err);
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={e => setFormData({...formData, name: e.target.value})}
placeholder="Name"
/>
<button type="submit">Create</button>
</form>
);
}
PUT Request (Update)
function UpdateStudent({ student }) {
const [formData, setFormData] = useState(student);
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch(
`http://localhost:5000/api/students/${student.id}`,
{
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
}
);
if (!response.ok) throw new Error('Failed to update');
const updated = await response.json();
console.log('Updated:', updated);
} catch (err) {
console.error(err);
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={e => setFormData({...formData, name: e.target.value})}
/>
<button type="submit">Save</button>
</form>
);
}
DELETE Request
function DeleteStudent({ studentId, onDelete }) {
const handleDelete = async () => {
if (!window.confirm('Are you sure?')) return;
try {
const response = await fetch(
`http://localhost:5000/api/students/${studentId}`,
{ method: 'DELETE' }
);
if (!response.ok) throw new Error('Failed to delete');
onDelete(studentId);
} catch (err) {
console.error(err);
}
};
return <button onClick={handleDelete}>Delete</button>;
}
API Service (Reusable)
Instead of fetch() everywhere, create an API service:
// api/studentService.js
const API_BASE = 'http://localhost:5000/api';
const studentService = {
getAll: async () => {
const response = await fetch(`${API_BASE}/students`);
if (!response.ok) throw new Error('Failed to fetch students');
return response.json();
},
getById: async (id) => {
const response = await fetch(`${API_BASE}/students/${id}`);
if (!response.ok) throw new Error('Student not found');
return response.json();
},
create: async (data) => {
const response = await fetch(`${API_BASE}/students`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to create');
return response.json();
},
update: async (id, data) => {
const response = await fetch(`${API_BASE}/students/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Failed to update');
return response.json();
},
delete: async (id) => {
const response = await fetch(`${API_BASE}/students/${id}`, {
method: 'DELETE'
});
if (!response.ok) throw new Error('Failed to delete');
return response.json();
}
};
export default studentService;
Usage:
import studentService from './api/studentService';
function StudentList() {
const [students, setStudents] = useState([]);
useEffect(() => {
studentService.getAll()
.then(data => setStudents(data))
.catch(err => console.error(err));
}, []);
return (
<ul>
{students.map(s => (
<li key={s.id}>{s.name}</li>
))}
</ul>
);
}
Authentication (JWT Tokens)
// Store token in localStorage after login
localStorage.setItem('token', jwtToken);
// Include in API requests
const studentService = {
getAll: async () => {
const token = localStorage.getItem('token');
const response = await fetch('http://localhost:5000/api/students', {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
}
};
Environment Variables
Create .env file:
REACT_APP_API_BASE=http://localhost:5000/api
Use in code:
const API_BASE = process.env.REACT_APP_API_BASE;
const response = await fetch(`${API_BASE}/students`);
CORS Issues
If frontend and backend are on different ports, you'll get CORS errors. Configure in ASP.NET:
// Program.cs
var builder = WebApplicationBuilder.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors();
Real Example: Student Management CRUD
import studentService from './api/studentService';
function StudentManagement() {
const [students, setStudents] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
loadStudents();
}, []);
const loadStudents = async () => {
try {
setLoading(true);
const data = await studentService.getAll();
setStudents(data);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
const handleCreate = async (newStudent) => {
try {
const created = await studentService.create(newStudent);
setStudents([...students, created]);
} catch (err) {
setError(err.message);
}
};
const handleDelete = async (id) => {
try {
await studentService.delete(id);
setStudents(students.filter(s => s.id !== id));
} catch (err) {
setError(err.message);
}
};
if (loading) return <p>Loading...</p>;
return (
<div>
{error && <p className="error">{error}</p>}
<CreateStudentForm onCreate={handleCreate} />
<StudentList
students={students}
onDelete={handleDelete}
/>
</div>
);
}
Key Takeaways
- Use fetch or axios for API calls
- Create reusable API services
- Handle errors and loading states
- Store API base URL in env variables
- Configure CORS on backend
- Next: Routing for multiple pages
- No error handling — App crashes on bad response
- Hardcoded URLs — Can't change between dev/prod
- No loading state — UI looks broken
- Not handling CORS — Requests fail mysteriously
Axios simplifies API calls:
import axios from 'axios';
const response = await axios.get('/api/students');
await axios.post('/api/students', data);
await axios.put(`/api/students/${id}`, data);
await axios.delete(`/api/students/${id}`);
Use ChatGPT, Claude, or Copilot to go deeper on API Integration. Try these prompts:
"What's the difference between fetch and axios?""Why should you create an API service instead of using fetch directly?""How do you handle authentication tokens in API requests?""Quiz me on API integration"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Quick Definitions
- API Integration — Fetching from .NET Web API - The main React concept explained in this lesson.
- Component - A reusable function that returns UI.
- Props/state/effects - Core React ideas used to pass data, remember data, and run side effects.
- Real project usage - How this appears in forms, dashboards, routes, and API-connected pages.
Common Mistakes
- Copying React code without understanding data flow
- Mutating arrays or objects directly instead of creating new values
- Forgetting keys, dependencies, loading states, or error states where needed
- Putting too much logic in one component
- Not testing the screen with realistic School Management System data
Practice Task
Create a small React example using API Integration — Fetching from .NET Web API. Keep it focused on one School Management System screen.
Suggested practice:
- Build a small component or page for students, attendance, marks, or fees.
- Pass realistic data into the component.
- Add one success state and one empty/error state where relevant.
- Explain the data flow in your own words.
- Rebuild the same example once without looking at the article.
Quick Revision
| Question | Answer |
|---|---|
| What is the main idea? | Understand and apply API Integration — Fetching from .NET Web API in React. |
| Where is it used? | Student dashboards, forms, tables, routes, and API-connected screens. |
| What should beginners focus on? | Clear components, predictable data flow, and small examples. |
| What is the best debugging habit? | Check props, state, render output, and browser console step by step. |
API Integration — Fetching from .NET Web API is a React concept used to build clear, reusable, and predictable user interfaces. I would explain the problem it solves, show a small component example, and mention a common mistake beginners should avoid.
It is used in screens like student lists, admission forms, attendance dashboards, marks reports, routing pages, and API-connected admin panels.