.NET APIs Part 4 – Creating the APIs

We are, finally, ready to create our ASP.NET Core application that will host our traditional and our minimal APIs. (This series begins here.)

The code for this blog post is available here:
git clone https://github.com/JesseLiberty/Cars.git

Please note that WordPress seems to be broken and so the layout will be imperfect.

To get started, open Visual Studio 2022 and make sure you are fully up to date. Click on Create A New Project and select ASP.NET Core Web App, making sure that C# is the selected language

Give your project a name and a location

Choose .NET 7 as your Framework with no authentication and click Create.

If you’ve been following along with this tutorial already, you can steal from your earlier project. Otherwise, just type in the code.

Let’s start in appsettings.json where we will add the connection string to connect us to the database we created last time


Key to creating your API is to create controllers. A controller is the class that holds the start of the logic that your API will use. This is much easier to demonstrate than to explain. Start by creating a folder named Controllers

Right click on your Controllers folder and create a class named CarController. For now, all our APIs will originate here. Let’s set up the top of the file by declaring a logger (supplied by Microsoft in the Microsoft.AppNetCore.MVC namespace) and an instance of our CarRepository


We’ll be using REST for our APIs. There is much that you can know about REST, but for our purposes all we need to know is that we’ll be using the standard HTTP keywords to Post (Create), Get (Read), Put (Update) and Delete (Delete).

Starting Data

To have data to work with, I downloaded the Car Information Dataset from Kagel (Please read their licensing agreement before using this data elsewhere). I modified the CSV file to add an id column and an is_deleted column.

I then imported this data into a table, following the directions in this excellent tutorial. Finally, I dropped the id column and added it back as the identity column.

alter table car
add car_id_new int identity(1,1)

alter table car drop column id

exec sp_rename 'car_id_new', 'id'

At this point, I have a table with all the columns from the imported data, as well as an identity column.

Go to your car class (that we created in part 3) and modify it as follows (to match the incoming data):

public class Car
    public int id { get; set; }
    public string name { get; set; } = null!;
    public string mpg { get; set; } = null!;
    public string cylinders { get; set; } = null!;
    public string displacement { get; set; } = null!;
    public string horsepower { get; set; } = null!;
    public string weight { get; set; } = null!;
    public string acceleration { get; set; } = null!;
    public string model_year { get; set; } = null!;
    public string origin { get; set; } = null!;
    public string? is_deleted { get; set;}

Note that for now we are keeping things very simple. We will not declare DTOs, and so we will not deal with mapping. We’ll save that for a later blog post.

Creating Our First API

We are ready to create our first API. Its job will be to get all the cars in the database. We’ll do this by creating the API in a controller class and then invoking a method in our Car repository.

Create a Controllers folder, if you have not already, and in that folder create a CarController class. Add the following code to the top of the class:

    public class CarController : ControllerBase
        private readonly ILogger<CarController> _logger;
        readonly CarRepository carRepository;

        public CarController(ILogger<CarController> logger,
            CarRepository carRepository)
            _logger = logger;
            this.carRepository = carRepository;

ControllerBase and ILogger are provided by Microsoft (thanks Satya!). Now, let’s create our API, which is a method decorated with the [HttpGet] attribute


Deceptively simple. This method returns a list of Car objects by calling GetAll on the carRepository. Let’s go look at that method:

(If you don’t already have a folder Repositories, please create one and add the class CarRepository). Here’s the top of the class:

You will need a using statement for Dapper.

We are now ready to implement the GetAll method:


This method will return the list of Car objects that we need, and defaults to not returning deleted records. We begin by creating a SqlBuilder – an object provided by Dapper. We then create our template, ending it with the syntax /**where**/ — this too is for Dapper and allows us to dynamically create our where clause.

You see this in the if statement; we’ll only add the where statement that restricts the results to non-deleted records if the parameter (returnDeletedRecords) is false.

Next we obtain a connection to the DataBase from our databaseConnectionFactory and finally we use that connection to call QueryAsync, identifying the type (Car) and passing in the SQL statement and the parameters to that statement, if any. In this simplified case we do not have any parameters, but we’ll see how to use them in a later blog post.

Testing with Postman

When you run your application Swagger will come up. Minimize that and open Postman, which is much more powerful and easier to work with (especially once we add authorization). Create a folder named Cars (of course, you can actually name it anything you like) and next to that folder click on the three dots that appear when you click on the name of the folder.

Choose Add Request, and rename your new request GetCars. Go to the right hand pane, and make sure the drop down is set to Get. Next to the drop down enter


Be sure to substitute the port number (bold) to the one used by Swagger.

That’s all you have to do. Click Send in the upper right hand corner and your API will be called (don’t be afraid to set break points to prove this to yourself) which will call the method in the repository, which will in turn fetch your data from the database and it will all be returned to Postman…

Congratulations! You have your first working API to your back-end data stored in SQL Server!

In this coming blog posts we’ll add the remaining CRUD APIs, examine using services and DTOs and take a look at minimal APIs.

Rodrigo Juarez is a full-stack developer who has specialized in Xamarin in recent years and is now focusing on MAUI. He is also a book author. With over 25 years of experience, Rodrigo has contributed to a diverse array of projects, developing applications for web, desktop, and mobile platforms. Specialized in Microsoft technologies, he has expertise across various sectors, including management, services, insurance, pharmacy, and banking. Rodrigo Juarez can be reached at info@rodrigojuarez.com

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in API, Essentials. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.