Skip to content

C# WebApi - A quick refresher

Lets write a C# minimal API application. We're going to save a string to a SQLite database. We will accept a single that would persist into a SQLite database through this RESTful API using minimal API.

Step 1: Create a New .NET Minimal API Project

sh
dotnet new web -n StringToDbApi
cd StringToDbApi

You will now have a simple project with following structure:

To run the project dotnet run in the terminal and you should see the Hello World output in the browser (URL: http://localhost:5154/).

Step 2: Add Necessary NuGet Packages

Now, let's add the SQLite dependancy

sh
# SQLite support for Entity Framework Core
dotnet add package Microsoft.EntityFrameworkCore.Sqlite

# Required for EF Core tools and migrations
dotnet add package Microsoft.EntityFrameworkCore.Design

You may now verify that the packages were added by checking the StringToDbApi.csproj file.

Step 3: Create a Database Context and a Model

Let's save a string value to the SQLite database!

  1. Create a new file named StringContext.cs in the root of your project.
  2. Save the below content to that file.
csharp
using Microsoft.EntityFrameworkCore;

namespace StringToDbApi
{
	// `StringContext` manages the connection to the SQLite database
	// and provides a `DbSet` for CRUD operations
    public class StringContext : DbContext
    {
        public DbSet<StringData> Strings { get; set; }

        public StringContext(DbContextOptions<StringContext> options)
            : base(options)
        {
        }
    }

	// StringData represents the table structure 
	// where strings will be stored
    public class StringData
    {
        public int Id { get; set; }
        public string Content { get; set; }
    }
}

Step 4: Configure the Database in the Program.cs

We're going to create two API Endpoints: - POST /save: Save a string to the database. - GET /strings: Retrieve all saved strings.

Add the two imports for EntityFrameworkCore and StringToDbApi to the Program.cs to configure and register the StringContext with the dependency injection container. Then add the end points as follows:

csharp
using Microsoft.EntityFrameworkCore;
using StringToDbApi;

// below line will be already there from the initial 
// hello world scaffolding code
var builder = WebApplication.CreateBuilder(args);

// Add services to the container. 
builder.Services.AddDbContext<StringContext>(options => { 
	options.UseSqlite("Data Source=Strings.db"); 
	});

// below line will be already there from the initial 
// hello world scaffolding code
var app = builder.Build();

// Run migrations and ensure database is created. 
using (var scope = app.Services.CreateScope()) { 
	var dbContext = scope.ServiceProvider.GetRequiredService<StringContext>(); 
	dbContext.Database.Migrate(); 
	}

// Minimal API endpoints. 
app.MapPost("/save", async (StringData stringData, StringContext context) => { 
	context.Strings.Add(stringData); 
	await context.SaveChangesAsync(); 
	return Results.Created($"/save/{stringData.Id}", stringData); 
	});

app.MapGet("/strings", async (StringContext context) => { 
   var strings = await context.Strings.ToListAsync(); 
   return Results.Ok(strings); 
   });

// below line will be already there from the initial 
// hello world scaffolding code
app.Run();

Below is a full code listing of the same so that you can double check. Note the comments as they're set to help the reader to understand what's being done ():

csharp
using Microsoft.EntityFrameworkCore;
using StringToDbApi;

// below line will be already there from the initial 
// hello world scaffolding code
var builder = WebApplication.CreateBuilder(args);

// Add services to the container. 
builder.Services.AddDbContext<StringContext>(options =>
{
    options.UseSqlite("Data Source=Strings.db");
});

// below line will be already there from the initial 
// hello world scaffolding code
var app = builder.Build();


// Run migrations and ensure database is created. 
using (var scope = app.Services.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<StringContext>();
    dbContext.Database.Migrate();
}


// below line will be already there from the initial 
// hello world scaffolding code. This line could be 
// removed as well if you don't need it anymore..
// we won't be talking about this line further as well.
app.MapGet("/", () => "Hello World!");


// Minimal API endpoints. 
app.MapPost("/save", async (StringData stringData, StringContext context) =>
{
    context.Strings.Add(stringData);
    await context.SaveChangesAsync();
    return Results.Created($"/save/{stringData.Id}", stringData);
});

app.MapGet("/strings", async (StringContext context) =>
{
    var strings = await context.Strings.ToListAsync();
    return Results.Ok(strings);
});

// below line will be already there from the initial 
// hello world scaffolding code
app.Run();

Do a Migration so that the table is created:

Run the following command in the terminal to create an initial migration:

# Following will create the `Strings.db` file and set up the `Strings` table as defined in your `StringContext`.

dotnet ef migrations add InitialCreate

Apply the Migration if you're doing and updates to the model:

dotnet ef database update

Run the application:

dotnet run

Step 5: Testing the application

Let's insert a string called Hello, SQLite! into our database (run the below in terminal):

sh
curl -X POST http://localhost:5154/save -H "Content-Type: application/json" -d '{"content":"Hello, SQLite!"}'

Example output:

Let's query the values:

sh
curl http://localhost:5154/strings

Example output:

References

© 2023-2025 Maduranga Kannangara. Feel free to use or share this content. Attribution is appreciated but not required.