A Definitive Guide to Understanding Web API in ASP.NET Core

Web API in ASP.NET Core

When it comes to building resilient and high-performance RESTful services, most developers prefer the ASP.NET Core framework. ASP.NET Core Web APIs enable seamless communication between software components and secure data sharing across different networks, devices, and operating systems. 

Using ASP.NET Core means getting easy access to reliable and robust .NET development services that enhance performance and processing power, positioning your application as unrivalled in the market. 

In this article, we will explore how to leverage .NET Core’s capabilities to build secure, scalable, and sophisticated Web APIs that can handle complex data exchanges through JSON while delivering an unparalleled user experience. 

1. What is a Web API?

Web API

A Web API is a specialized set of protocols and tools that enables different software applications to communicate with each other over the internet. It acts as a mediator between a web server and various clients, such as mobile apps, web browsers, or desktop applications, facilitating a seamless exchange of data and services. Web APIs use standardized protocols, such as HTTP, to establish clear guidelines and conventions for requesting and delivering information. 

It also enables the integration of third-party services through a server-client architecture, connecting frontend interfaces with backend servers. This approach facilitates communication between the two without requiring navigation of the complexities of each system. 

Web APIs are essential in modern software development as they act as a bridge between different kinds of apps to enable interactions and the sharing of resources in a unified manner.

2. Why Do We Need Web APIs?

Web APIs are essential because they act as a centralized hub for business logic, eliminating the need to write and maintain duplicate code across multiple platforms, like websites, Android, and iOS.

Without web APIs, developers would need to duplicate application logic for every platform, significantly increasing the risk of errors and the maintenance burden. Placing the API between the client applications and the database ensures that all platforms follow the same interaction rules, making it easier to manage and scale the entire system. 

Many modern front-end technologies cannot communicate directly with a database, but can easily interact with APIs using standard web protocols. Moreover, APIs improve performance by exchanging data in lightweight formats such as JSON or XML. This reduces bandwidth usage compared to loading full web pages, ensuring that mobile and web applications remain fast and responsive for users.

3. What are the Types of Web APIs?

Before using ASP.NET to create Web APIs, it is important to determine the type of API you need to build. This section explains different types of Web APIs, categorized based on their accessibility and range of applications. 

3.1 Private API

As the name suggests, a Private API is strictly limited to a specific group of users and cannot be accessed by the general public. These APIs are designed exclusively for internal use within a company or organization and are never meant to be shared outside a certain set of users. Private APIs are used to connect an organization’s software with other internal systems. For example, a company might use a private API to integrate its payroll and human resources software.

3.2 Composite API

This API combines multiple API calls into a single request to reduce the round-trip time for each call. As a result, your app’s speed and effectiveness improve significantly. Composite API enables you to process multiple queries within a single database transaction. Using the Composite API, you can make various requests in one call, such as updating purchase history, checking inventory, and validating payment details while placing an order. One of the most valuable applications of a composite API is in the e-commerce industry. 

3.3 Partner API

This kind of API is available for particular users. Users with proper credentials or who are truly trustworthy are given access to partner APIs. These APIs provide business-to-business transactions and collaboration. For example, CRM systems need to access client data to function properly. Organizations use partner APIs to selectively share customized data with third-party services. 

3.4 Open Source API

The APIs that are publicly available for free use in software development are called Open-source or Public API. Since they are not restricted to any particular user, you can easily integrate them with other software systems. Developers leverage Public APIs, also known as external APIs, to access specific data and features from third-party software to use in their applications. Some of the most popular APIs readily accessible from the public domain include the JSONPlaceholder API, Google Translate API, GraphQL, and Websocket.

4. How to Build a Web API with ASP.NET Core?

Follow this step-by-step guide to understand how to use ASP.NET Core to create a Web API. 

4.1 Prerequisite

You will need the following things to start this project. 

  • Visual Studio 2022 Community Edition
    Why: best-in-class developer tooling for .NET (project templates, integrated debugging, NuGet UI, and easy IIS/IIS Express support). 
  • .NET SDK (preferably .NET 8)
    Why: latest LTS features, performance improvements, and up-to-date EF Core compatibility.

4.2 Create a New Web API Project

Follow the given steps to create a new project for building a web API in Visual Studio Code.

1.1 Open Visual Studio → Create New Project.

Create New Project

1.2 Choose ASP.NET Core Web API → Next.

ASP.NET Core Web API

1.3 Make the following Configurations:

Project Name: CarAPI 

Framework: .NET 8 Check

Enable OpenAPI (Swagger) and Use Controllers

Why these settings? 

  • Using controllers will provide an explicit and familiar structure for routing and HTTP verbs. 
  • Enabling OpenAPI automatically adds the Swagger UI. This helps with manual testing and documentation.
Configure your new project
Additional information

4.3 Project Structure (Default)

Project Structure (Default)

4.4 Install EF Core Packages

Command (PMC or Visual Studio Terminal):

NuGet Package Manager

Why use these packages? 

  • Microsoft.EntityFrameworkCore — EF Core ORM that maps C# objects to DB tables. 
  • Microsoft.EntityFrameworkCore.SqlServer — SQL Server provider. 
  • Microsoft.EntityFrameworkCore.Tools — migrations & design-time tools.

Tip: For .NET 8, ensure the EF Core package versions match (EF Core 8.x).

EF Core package versions match

Verify if the installation of the packages is completed successfully.

4.5 Create the Entity Model

Go to the location mentioned below in your project and use the given code to create the entity model. 

Location: Models/Car.cs

namespace CarAPI.Models
{
    public class Car
    {
        public int CarId { get; set; }
        public string Model { get; set; } = string.Empty;
        public DateTime LaunchDate { get; set; }
        public string Company { get; set; } = string.Empty;
        public int Price { get; set; }
        public string FuelType { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
    }
}

Why use non-nullable strings with = string.Empty;? 

  • Non-nullable strings ensure that the property is required at runtime while avoiding compiler warnings. The EF Core creates a NOT NULL column for non-nullable reference types.

4.6 Setup EF Core + Create Database Context

Navigate to the mentioned location and use the code below to create a database context. 

Location: Data/AppDbContext.cs

using CarAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace CarAPI.Data
{
    public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
    {
        public DbSet<Car> Cars { get; set; }
    }
}

4.7 appsettings.json — Connection String

"ConnectionStrings": {
  "DefaultConnection": "Server=Your_Server_Name;Database=CarDb;Trusted_Connection=True;TrustServerCertificate=True;"
}

Why store the connection string here? 

  • Centralized environment-specific config; avoids hard-coding secrets in code. Replace with secure secret store or environment variables in production.

4.8 Create DTOs for POST/PUT (Hide Identity)

Why build DTOs? 

  • The DB is represented by entities, whereas the API contract is represented by DTOs. This separation prevents over-posting, protects internal DB fields, and supports versioning. 
  • DTOs ensure that Swagger displays the correct JSON schema (e.g., POST should not require a CarId).

📁 DTOs → CreateCarDto.cs

namespace CarAPI.DTOs
{
    public class CreateCarDto
    {
        public string Model { get; set; }
        public DateTime LaunchDate { get; set; }
        public string Company { get; set; }
        public int Price { get; set; }
        public string FuelType { get; set; }
        public string Description { get; set; }
    }
}

4.9 Create Repository Layer

Why are we using an interface + repository pattern? 

  • Abstraction: ICarRepository provides a contract. Controllers are highly dependent on the interface, and not on the concrete class (dependency inversion). 
  • Testability: Unit testing enables you to mock ICarRepository interface. 
  • Separation of concerns: Keeps data access logic centralized, preventing SQL from leaking into controllers. 
  • Single responsibility: The repository handles data retrieval/storage; controllers handle HTTP requests and validation.

📁 Repository → ICarRepository.cs

using CarAPI.Models;
namespace CarAPI.Repository
{
    public interface ICarRepository
    {
        Task<IEnumerable<Car>> GetAllAsync();
        Task<Car> GetByIdAsync(int id);
        Task<Car> AddAsync(Car car);
        Task<Car> UpdateAsync(Car car);
        Task<bool> DeleteAsync(int id);
    }
}

📁 Repository → CarRepository.cs

using CarAPI.Data;
using CarAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace CarAPI.Repository
{
    public class CarRepository : ICarRepository
    {
        private readonly AppDbContext _context;
        public CarRepository(AppDbContext context)
        {
            _context = context;
        }
        public async Task<IEnumerable<Car>> GetAllAsync()
        {
            return await _context.Cars.ToListAsync();
        }
        public async Task<Car> GetByIdAsync(int id)
        {
            return await _context.Cars.FindAsync(id);
        }
        public async Task<Car> AddAsync(Car car)
        {
            _context.Cars.Add(car);
            await _context.SaveChangesAsync();
            return car;
        }
        public async Task<Car> UpdateAsync(Car car)
        {
            _context.Cars.Update(car);
            await _context.SaveChangesAsync();
            return car;
        }
        public async Task<bool> DeleteAsync(int id)
        {
            var car = await _context.Cars.FindAsync(id);
            if (car == null) return false;
            _context.Cars.Remove(car);
            await _context.SaveChangesAsync();
            return true;
        }
    }
}

Implementing the Example: CarRepository 

  1. Use the AppDbContext 
  2. Execute the methods with EF Core async calls such as ToListAsync(), FindAsync(), and SaveChangesAsync().

4.10 Register Repository & EF

This step requires you to take two actions as mentioned below: 

  1. Register EF in the Program.cs 
  2. Register the Repository in the Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddScoped<ICarRepository, CarRepository>();

Why AddScoped? 

  • One DbContext per HTTP request makes a scoped lifetime perfect for DbContext/repository, aligning with the request lifetime.

4.11 Create Controller

File: Controllers/CarController.cs (you already have it) 

Why keep the controller thin? 

  • The controller must coordinate DTO validation, call the service/repository, and send a suitable response. A service layer (if present) should house business rules, not controllers. 

Key endpoints 

  • GET /api/car → Get all cars 
  • GET /api/car/{id} → Get single car 
  • POST /api/car → Create car (accepts CarCreateDto) 
  • PUT /api/car/{id} → Update car (accepts CarUpdateDto) 
  • DELETE /api/car/{id} → Delete 

📁 Controllers → CarsController.cs

using CarAPI.DTOs;
using CarAPI.Models;
using CarAPI.Repository;
using Microsoft.AspNetCore.Mvc;
namespace CarAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CarController : ControllerBase
    {
        private readonly ICarRepository _repo;
        public CarController(ICarRepository repo)
        {
            _repo = repo;
        }
        [HttpGet]
        public async Task<IActionResult> GetAll()
        {
            return Ok(await _repo.GetAllAsync());
        }
        [HttpGet("{id}")]
        public async Task<IActionResult> Get(int id)
        {
            var car = await _repo.GetByIdAsync(id);
            if (car == null) return NotFound();
            return Ok(car);
        }
        [HttpPost]
        public async Task<IActionResult> Create(CreateCarDto dto)
        {
            var car = new Car
            {
                Model = dto.Model,
                LaunchDate = dto.LaunchDate,
                Company = dto.Company,
                Price = dto.Price,
                FuelType = dto.FuelType,
                Description = dto.Description
            };
            var createdCar = await _repo.AddAsync(car);
            return CreatedAtAction(nameof(Get), new { id = createdCar.CarId }, createdCar);
        }
        [HttpPut("{id}")]
        public async Task<IActionResult> Update(int id, CreateCarDto dto)
        {
            var existingCar = await _repo.GetByIdAsync(id);
            if (existingCar == null) return NotFound();
            existingCar.Model = dto.Model;
            existingCar.LaunchDate = dto.LaunchDate;
            existingCar.Company = dto.Company;
            existingCar.Price = dto.Price;
            existingCar.FuelType = dto.FuelType;
            existingCar.Description = dto.Description;
            var updatedCar = await _repo.UpdateAsync(existingCar);
            return Ok(updatedCar);
        }
        [HttpDelete("{id}")]
        public async Task<IActionResult> Delete(int id)
        {
            var deleted = await _repo.DeleteAsync(id);
            if (!deleted) return NotFound();
            return Ok("Car deleted successfully");
        }
    }
}

At last project folder structure looks as follows:

Project folder structure

4.12 Apply Migrations

Commands (Terminal / VS Terminal):

Apply Migrations

Add-Migration InitialCreate

Update-Database

Create a Migration folder as shown in the image below:

Migration folder

Why migrations? 

  • Using EF Core code-first migrations, you can track DB schema changes in source control, safely evolve the database schema, and easily set up on other machines and CI. 

CarDb has been created in your DB

4.13 Run the Project and Swagger

Press IIS Express (or run via dotnet run) to run the project. 

For Swagger: 

  • Go to /swagger for automatically generated interactive API docs. 
  • Try the POST body, as the example JSON won’t show CarId because you use DTOs. 

Click IIS Express → Swagger will launch.

IIS Express

4.14 Test the API

Manual testing with Swagger or Postman 

  • POST JSON (without CarId) 
  • GET to check entry 
  • PUT to modify (send CarId in URL and DTO) 
  • DELETE to remove 

Tip: Check the DB table to confirm data inserted.

Check the DB table to confirm data inserted

Use the Get method to get the DB record

Get method to get DB record

You can also check the car record in the DB

check car record in DB

5. Conclusion

ASP.NET Core Web API is a robust framework for building fast, scalable, and secure HTTP and RESTful services accessible across various clients. It enables a centralized backend to communicate with different clients, ensuring the app works efficiently across all platforms, including web, mobile, and desktop. ASP.NET Core provides a wide range of features to create web apps and APIs. If you are considering building a web application on the .NET platform, then ASP.NET Core is an ideal option. You can also use MVC patterns to design more flexible Web APIs. 

FAQs

Is ASP.NET Core Web API RESTful?

Yes, ASP.NET Core uses the C# programming language to support the creation of RESTful services, commonly known as Web APIs. They utilize controllers to manage requests. Controllers are basically classes derived from ControllerBase in Web API. 

How to Integrate an API in ASP.NET Core?

Here is a step-by-step process for integrating the Web API in ASP.NET Core. 

  1. Create the ASP.NET Core Web API Project.
  2. Define the Data Model.
  3. Integrate Entity Framework Core.
  4. Configure the Database Connection.
  5. Apply Migrations.
  6. Create the Controller.
  7. Test the RESTful API.

Why Do We Use Web API in ASP.NET Core?

Web APIs allow you to build services that run on different entities, making it easy for developers to build ASP.NET apps that are compatible with multiple devices and browsers. 

Which Architecture is Best for .NET Core Web API?

Clean architecture is highly recommended because it adheres to the principle of separation of concerns, allowing each module to operate independently of the other.

profile-image
Rakesh Patel

Rakesh Patel is a technology expert working at TatvaSoft. He is looking after .NET development projects and also work along side with business analyst team. He developed his passion of writing while working and writes whenever he got the time.

Comments

Leave a message...