ASP.NET Web API Backend: Part 1
In the last few lessons, we learned about the Backend development with C#, relational databases, and that ASP.NET Core is the framework for building web applications with C#. This is all prerequisite knowledge for what we are about to do now.
I’m going to show you how we can build a RESTful Web API with C# and ASP.NET.
This is going to be a practical example which you can directly apply to real world projects.
Our simple app will contain one RESTful Web API controller with endpoints to perform CRUD operations. Later, we will use Entity Framework to persist data to a SQL Server database.
Let’s get started.
You can download the finished version of this backend development sample: part 1 from our GitHub page
Create Project
Open up Visual Studio 2022 and create a new project. Here is where the confusion begins since there are so many options to choose from! Typing Web API will narrow the list down a bit.
A web API is a program that runs on a server. It contains business logic that manipulates data in a database. Functionality is exposed via API endpoints so that some kind of user interface can sit on top of that and control it. In this tutorial, we’ll use a developer tool called Postman to interact with the endpoints directly instead of building a user interface. Later, we will adapt the front-end client we created in the first module to use this web API.
The project template we’ll choose for this is the one called ASP.NET Core Web API. This one is the most practical since it’s got a bit of code already done for us. Once you become a skilled ASP.NET developer, using Nano ASP.NET Boilerplate can save you a lot of effort when building new projects instead of using these basic project templates.
Once you select ASP.NET Core Web API, continue to the next screen and select the latest .NET version. Our simple application won’t have any authentication. Just leave all the other options with their default selection.
Create an API Controller
First remove the sample Weather controller / class from the project – these are created by default as part of the ASP.NET Core Web API template.
Next right-click the Controllers folder and create a new Controller. Within a project you can name folders whatever you want, but certain folder names are special to the framework like Controllers.
Remember that a framework is a like a pre-existing collection of code to build something specific, in this case a web application. C# is the programming language used within ASP.NET. Some other examples of web application frameworks would be like Lavarel which uses PHP, or Django which uses python.
Name the new controller, ProductsController and choose blank web API controller.
A RESTful controller is an API endpoint that follows a particular REST standard, which stands for Representation State Transfer. REST is a fancy term which means that it contains the four standard HTTP methods: Get, Post, Put, and Delete. The entire internet runs on these commands!
The difference between API controllers and MVC controllers is that MVC controllers return pages, which is not what we want. Those controllers are for the old style of developing web applications, whereas API controllers are more common today and return only data. API controllers are used with single page applications (SPAs) that dynamically load data.
By continuing with this tutorial, you will quickly learn how to build modern web applications using C# and ASP.NET. And once you get good at things, you’ll want to build more sophisticate and scalable apps. The Nano ASP.NET Boilerplate is a premium project template that incorporates all the best practices into a solution that generate on unlimited projects. All of the tedious foundational work, like authentication, user management, and infrastructure, has been taken care. It’s well documented, complete with an admin UI in React, Vue, and Razor pages.
Create API Endpoints
Within our controller we will create all four REST methods, starting with Get.
Create a new method which returns an IActionResult called GetProducts. Place an HttpGet attribute before the method code to identify it as a Get endpoint.
An IActionResult is a built-in interface (similar to an object), which contains all the standard response codes like 200 OK or 404 NotFound. Our API methods will return an OK response along with a message just to see something happening. When we test with Postman, the endpoints will receive these requests and display messages as a response.
// full list
[HttpGet]
public IActionResult GetProducts()
{
var response = "Get List of Products";
return Ok(response);
}
Create another Get endpoint, this time with a parameter for the id within the HttpGet attribute. Multiple endpoints of the same type can exist as long as they have a different signature.
This endpoint will be called GetProductById and it will receive an integer id parameter. Even though there are now two Get endpoints, the ASP.NET framework will know which endpoint to direct traffic to based on whether or not an id is being passed with the request.
// single by Id
[HttpGet("{id}")]
public IActionResult GetProductById(int id)
{
var response = "Get Products with ID: " + id;
return Ok(response);
}
Create a new endpoint called CreateProduct and precede this method with an HttpPost attribute. For Post requests, its necessary to send up an object (the new product) in the body of the request. Including a message body will be handled on the client-side but we do need to define how that data is expected on the server-side. To do that, we will create a DTO Class which stands for Data Transfer Object.
We will have several DTOs in our application so create a new folder called DTOs within the project. The first DTO we need is for defining the structure of a new product request. Right-click the DTOs folder and create a new class called CreateProductRequest. Within the class, create string properties for Name and Description. In Visual Studio you can type prop and then hit tab to auto generate some code for property names. The { get; set; } is just shorthand which means that these properties can be read and write.
public class CreateProductRequest
{
public string Name { get; set; }
public string Description { get; set; }
}
Back in the controller, add this DTO class as a parameter called request (you could name it anything). This parameter now makes it so that any request body sent to this endpoint needs to have that structure.
// create
[HttpPost]
public IActionResult CreateProduct(CreateProductRequest request)
{
Random random = new Random();
int id = random.Next(1, 100);
var response = "Create a new product with ID: " + id + " and NAME: " + request.Name;
return Ok(response);
}
Next make a new method called UpdateProduct. This will have an HttpPut attribute with an id parameter. We’ll pass in two parameters to the method itself, first a new DTO called UpdateProductRequest to define the body structure, and next an integer value for the id of the product to be updated, which we obtain from the HttpPut attribute.
// update
[HttpPut("{id}")]
public IActionResult UpdateProduct(UpdateProductRequest request, int id)
{
var response = "Create a new product with ID: " + id + " and NAME: " + request.Name;
return Ok(response);
}
Create a class in DTOs for UpdateProductRequest like shown. Even though in our simple application it’s identical to CreateProductRequest, it’s common to make separate classes for create and update. In a real world application, there are usually properties which are only changed during create, or only changed during update.
public class UpdateProductRequest
{
public string Name { get; set; }
public int Description { get; set; }
}
Let’s finish the Products API controller with one final endpoint for Delete. Add a new method and precede it with the HttpDelete attribute and a parameter for the product id. This parameter will pass through to the method as an integer value. The method will return an OK response with a message saying the product was deleted.
// delete by Id
[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
var response = "Delete product with ID: " + id;
return Ok(response);
}
Our completed Products API controller should look like this now:
using Microsoft.AspNetCore.Mvc;
using SimpleWebApi.DTOs;
namespace SimpleWebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
// full list
[HttpGet]
public IActionResult GetProducts()
{
var response = "Get List of Products";
return Ok(response);
}
// single by Id
[HttpGet("{id}")]
public IActionResult GetProductById(int id)
{
var response = "Get Products with ID: " + id;
return Ok(response);
}
// create
[HttpPost]
public IActionResult CreateProduct(CreateProductRequest request)
{
Random random = new Random();
int id = random.Next(1, 100);
var response = "Create a new product with ID: " + id + " and NAME: " + request.Name;
return Ok(response);
}
// update
[HttpPut("{id}")]
public IActionResult UpdateProduct(UpdateProductRequest request, int id)
{
var response = "Create a new product with ID: " + id + " and NAME: " + request.Name;
return Ok(response);
}
// delete by Id
[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
var response = "Delete product with ID: " + id;
return Ok(response);
}
}
}
Testing the API
Eventually we would build a front-end user interface that interacts with these endpoints, but during development typically a tool like Postman is easier to test things.
Go to link and download Postman if you haven’t already.
Open Postman and create a new blank collection. In the variables tab, create a new variable called URL. Populate this value with the https address of your ASP.NET Core Web API application. This can be found in the properties folder launchSettings.json.

Within our Postman collection, create a new request and name it Get Products or something like that. In the address bar, ensure that Get is the type of request selected and start the address with the {{url}} variable followed by /products.

We can expect to hit our first endpoint with this type of API call. Click send to see what happens!
You should see a 200 OK response code and the phrase ‘Get list of products’ in the results window. This means that our web API is working and we can successfully hit our GetProducts endpoint.
Now create (or duplicate) this request and call it Get Product by ID. Add a forward slash and then some integer number like 123 as a test ID. Send the request to see what happens.
You should see another 200 OK response code and ‘Get product with ID: 123’ in the results window. ASP.NET routed our request once again to the correct endpoint.
Create a new request, this time a Post request. In Postman, select the Body tab under the address bar. Make sure raw JSON is selected. Add an object with Id and Name properties and send this request.

A 200 OK response will be returned with the ID and Name values added to the message. If any property was mistyped or absent in the object being sent, a 400 Bad Request would instead be returned.
Do the same with the update and delete product endpoint to ensure everything is working.
Conclusion
If you have made it this far, congratulations you know quite a bit about backend development with C#! You know how to send Http requests across planet earth and manipulate systems on the other side of the world, which is pretty cool.
What is even cooler though is the Nano ASP.NET Boilerplate. If you are an intermediate or advanced programmer, use it for building the next big idea. Or if you are just beginning, use it as a learning resource. It’s completely documented and a lot simpler to understand than other boilerplates for ASP.NET like ABP.
Next we’ll see how to do something more useful than just returning messages. We’ll set up a database with an ORM to manage and store data.