Building and Testing a .NET API: A Step-by-Step Guide
Table of contents
In this blog, I will show you how to create a .NET API, host it locally using Docker, and integrate it with a web application. We'll use Visual Studio Code as our primary development environment. This guide includes everything from setting up the environment to testing the API on a web application, making it perfect for beginners.
Note: I was working on a Mac during this project, which is why I chose Docker to containerize and host the API. Docker provides a consistent runtime environment that works across operating systems like macOS, Linux, and Windows, ensuring my API behaves the same on all platforms.
Prerequisites
Before we begin, ensure you have the following tools installed:
.NET SDK: Download .NET SDK
Docker: Get Docker
Azure Data Studio: Download Azure Data Studio
Basic Knowledge of C# and Web Development
Visual Studio Code Extensions
C#: For IntelliSense, debugging, and running .NET applications.
Docker: To manage Docker containers directly in VS Code.
SQL Server (mssql): For querying and managing the database with Azure Data Studio.
Step 1: Setting Up the .NET API
Open your terminal and navigate to the directory where you want to create the project.
Run the following command to create a new .NET API project:
dotnet new webapi -n MyApiProject
Navigate into the project folder:
cd MyApiProject
Restore dependencies and run the project:
dotnet restore dotnet run
The API will now be running locally at
http://localhost:5000
(orhttps://localhost:5001
for HTTPS).
Set Up Debugging in VS Code
Go to the Run and Debug tab and click on "Create a launch.json file."
Select
.NET
. Use the following configuration to enable debugging:{ "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (web)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", "program": "${workspaceFolder}/bin/Debug/net5.0/MyApiProject.dll", "cwd": "${workspaceFolder}", "serverReadyAction": { "action": "openExternally", "pattern": "\\bNow listening on: (https?://\\S+)" }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" } } ] }
Step 2: Adding Dapper for Database Operations
Install Dapper
Run the following command to install Dapper via NuGet:
dotnet add package Dapper
Create a Data Access Class
Add a new folder named
Data
in your project.Create a class for handling database operations, such as:
using Dapper; using System.Data.SqlClient; public class MyDataAccess { private readonly string _connectionString; public MyDataAccess(string connectionString) { _connectionString = connectionString; } public IEnumerable<MyModel> GetAllData() { using (var connection = new SqlConnection(_connectionString)) { return connection.Query<MyModel>("SELECT * FROM MyTable"); } } }
Define the Model
Add a folder named
Models
and create a class for the model:public class MyModel { public int Id { get; set; } public string Name { get; set; } }
Step 3: Setting Up Azure Data Studio
Open Azure Data Studio and connect to your server.
Create a New Database:
Right-click on the
Databases
node and selectNew Database
.Name it
MyDatabase
.
Create a Table:
Right-click on the
Tables
node and selectNew Table
.Add columns, such as
Id (int)
andName (varchar)
.Save the table.
Adding Sample Data to the Database
After creating the database and tables in Azure Data Studio, you can insert sample data using SQL queries or programmatically through your .NET API.
Insert Data Using SQL Queries in Azure Data Studio
Open Azure Data Studio and connect to the database.
Right-click on your database (e.g.,
MyDatabase
) and select New Query.Write and execute an INSERT query to add sample data to the table. For example, if your table is named
MyTable
with columnsId
andName
, you can use the following query:INSERT INTO MyTable (Id, Name) VALUES (1, 'John Doe'), (2, 'Jane Smith'), (3, 'Alice Johnson');
This will insert three sample records into the table.
Verify the Data: Run a SELECT query to ensure the data was added successfully:
SELECT * FROM MyTable;
You should see the inserted rows in the query results.
Alternative: Use a Database Seeder in Your API Code (Optional)
If you prefer, you can programmatically add the data from your .NET API by writing a database seeder function. This function would connect to the database and execute the necessary INSERT statements.
Example in C#:
using System.Data.SqlClient;
public class DatabaseSeeder
{
private readonly string _connectionString;
public DatabaseSeeder(string connectionString)
{
_connectionString = connectionString;
}
public void Seed()
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var query = @"
INSERT INTO MyTable (Id, Name) VALUES (1, 'John Doe');
INSERT INTO MyTable (Id, Name) VALUES (2, 'Jane Smith');
INSERT INTO MyTable (Id, Name) VALUES (3, 'Alice Johnson');
";
var command = new SqlCommand(query, connection);
command.ExecuteNonQuery();
}
}
}
You can call this Seed
method during the startup of your application to populate the database with sample data.
Where is the Data Being Sent from the API?
The data you’ve inserted into the database is fetched by the .NET API through the Dapper query defined in your data access class (MyDataAccess
). The GetAllData()
method sends a SELECT
query to the database and retrieves the rows you’ve inserted.
Example in C#:
public IEnumerable<MyModel> GetAllData()
{
using (var connection = new SqlConnection(_connectionString))
{
return connection.Query<MyModel>("SELECT * FROM MyTable");
}
}
This retrieved data is then exposed via an API endpoint and consumed by the React.js application. The API acts as a bridge between the database and the frontend, allowing the React.js application to access and display the data dynamically. Which we will create later as we finish with the API.
Step 4: Containerizing with Docker
Create a Dockerfile
In the root of your project, create a file named Dockerfile
with the following content:
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["MyApiProject/MyApiProject.csproj", "MyApiProject/"]
RUN dotnet restore "MyApiProject/MyApiProject.csproj"
COPY . .
WORKDIR "/src/MyApiProject"
RUN dotnet build "MyApiProject.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApiProject.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApiProject.dll"]
Build the Docker Image
Run the following command in the terminal:
docker build -t myapiproject:latest
Run the Docker Container
Start the container:
docker run -d -p 8080:80 --name myapicontainer myapiproject:latest
Your API will now be available at http://localhost:8080
.
Building a web application is essential to test and showcase the functionality of the .NET API effectively. While the API handles data and operations, it requires a user-friendly interface to make the data accessible and interactive. I chose to showcase the API through a web application to demonstrate its real-world use and validate that the endpoints work correctly by integrating it into a practical scenario. React.js was my framework of choice for this project because I have prior experience working with it, which allowed me to create a responsive and visually appealing frontend efficiently. React’s component-based architecture and seamless integration with APIs made it an ideal choice for dynamically fetching and displaying the data. By combining my knowledge of React.js with the power of the .NET API, I created a full-stack application that highlights both the backend's capabilities and the frontend's user-centric design.
Step 5: Creating the Web Application with React.js
Set Up a New React Project
Open the terminal and run the following commands to create a React.js project using
create-react-app
:npx create-react-app my-web-app cd my-web-app
Install Axios for API Requests
Axios is a popular library for making HTTP requests in React. Install it by running:
npm install axios
Create a Component to Fetch Data from the API
Inside the
src
folder, create a new file calledApiData.js
and add the following code:import React, { useState, useEffect } from 'react'; import axios from 'axios'; const ApiData = () => { const [data, setData] = useState([]); useEffect(() => { // Fetch data from the .NET API axios.get('http://localhost:8080/api/data') .then(response => { setData(response.data); }) .catch(error => { console.error('Error fetching data:', error); }); }, []); return ( <div> <h1>Data from .NET API</h1> <ul> {data.map((item, index) => ( <li key={index}>{item.name}</li> ))} </ul> </div> ); }; export default ApiData;
Integrate the Component into Your App
Open the
App.js
file and replace the default content with:import React from 'react'; import ApiData from './ApiData'; function App() { return ( <div> <ApiData /> </div> ); } export default App;
Start the React Application
Run the React app using:
npm start
Open
http://localhost:3000
in your browser. The app should display data fetched from the .NET API.
Conclusion
In this project, we demonstrated how data is seamlessly fetched from a .NET API and displayed in a React.js web application. The .NET API acts as the backend, handling data operations and serving it through endpoints. Using Axios, the React.js application makes HTTP requests to these API endpoints, retrieves the data, and dynamically renders it on the frontend. This process ensures real-time interaction, where any changes in the backend data can be immediately reflected in the user interface. By combining the strengths of the .NET API for robust backend logic and React.js for a responsive and dynamic frontend, we created a fully functional full-stack application that bridges the gap between data handling and user experience.
You can find the complete code for the .NET API in my GitHub repository: