Minimal API:
The concept of creating an HTTP API with minimal dependencies is Minimal APIs. It was introduced in Asp.Net 6, and they are ideal for microservices that can be finished with minimum files and features.
In Minimal API there won't be any controller or action methods. In Minimal API, the logical execution function will be registered along with the route registration.
On comparing Minimal API with the normal Web API, that Minimal API doesn't support(for Asp.Net Core 6 these won't support but in the upcoming versions, these may be available) the following features like:
- Minimal API doesn't support built-in validation.
- Minimal API doesn't support filters.
- Minimal API doesn't support versioning.
- Minimal API doesn't support OData.
Create A .Net6 Minimal API Project:
Let's create a .Net6 Minimal API sample project to accomplish our CRUD sample. We can use either Visual Studio 2022 or Visual Studio Code (using .NET CLI commands) to create any .Net6 application. For this demo, I'm using the 'Visual Studio Code'(Using .Net CLI commands) editor.
CLI command For Minimal API Project
dotnet new webapi -minimal -o Your_Project_Name
dotnet new webapi -minimal -o Your_Project_Name
From .Net6 onwards there will be no 'Startup.cs' file, so all registration configurations moved to the 'Program.cs' file. Now on creating the Minimal API project, we will get the 'WeatherForeCaste' test endpoint so let's remove all its references, and finally our 'Program.cs' file looks as below.
Program.cs:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.Run();Since the concept of Minimal API is to use a minimum number of files. Now in this demo, we are going to use 'Program.cs' file to write our business logic and database logic inside it.
Configure EntityFramework Core DbContext:
Let's install the entity framework core NuGet.
Package Manager:
Install-Package Microsoft.EntityFrameworkCore -Version 6.0.0
Install-Package Microsoft.EntityFrameworkCore -Version 6.0.0
.Net CLI:
dotnet add package Microsoft.EntityFrameworkCore --version 6.0.0
dotnet add package Microsoft.EntityFrameworkCore --version 6.0.0
Let's install the SQLServer dependent library of entity framework core NuGet.
Package Manager:
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.0
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.0
.Net CLI:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 6.0.0
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 6.0.0
Let's add the 'DbContext' at the end of the 'Program.cs' file.
Program.cs:
// Dbcontext public class MyWorldDbContext:DbContext { public MyWorldDbContext(DbContextOptions<MyWorldDbContext> options):base(options) { } public DbSet<Gadgets> Gadgets { get; set; } } // Database classes public class Gadgets { public int Id { get; set; } public string ProductName { get; set; } public string Brand { get; set; } public decimal Cost { get; set; } public string Type { get; set; } }Now register the 'AddDbContext' service.
Program.cs:
builder.Services.AddDbContext<MyWorldDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("MyWorldDbConnection")); });
Endpoint HTTP Methods:
In the Minimal API, execution logic will be registered along with the endpoint URL. Each endpoint can be registered with the appropriate HTTP method.
Get:
app.MapGet("", () => {});Post:
app.MapPost("", () => {});Put:
app.MapPut("", () => {});Delete:
app.MapDelete("", () => {});
Create Operation:
Let's implement the 'Create' operation endpoint for our Minimal API. let's begin adding our Endpoint Http Methods after the 'app.UseHttpsRedirection()' middleware.
Program.cs:
app.MapPost("/gadgets/create", async(Gadgets gadgets, MyWorldDbContext myWorldDb) => { myWorldDb.Gadgets.Add(gadgets); await myWorldDb.SaveChangesAsync(); return Results.Ok(); });
- (Line: 1) The 'MapPost' to create the HTTP Post endpoint. This method takes 2 input parameters where the 1st parameter is 'URL' and 2nd parameter is the delegate function that contains all execution logic of our Minimal API.
- The Delegate handler we created as an asynchronous method. This Delegate handler is a custom method and here passes parameters like 1st parameter like payload of type 'Gadgets' and 2nd parameter is injected 'DatabaseContext'.
- (Line: 2-3) Logic to save data to the database.
- (Line: 4) Returning 'Ok' API response.
Read Operation:
Let's implement the 'Read' operation endpoint.
Program.cs:
app.MapGet("/gadgets", async (MyWorldDbContext myWorldDb) => { var gadgets = await myWorldDb.Gadgets.ToListAsync(); return Results.Ok(gadgets); });
- (Line: 1) The 'MapGet' method represents HTTP get endpoint. The 'MapGet' method has 2 parameters like 1st parameter is 'URL' and 2nd parameter is 'Delegate'.
- The 'Delegate' is implemented as an asynchronous method. Injected 'DatabaseContext' as an input parameter.
- (Line: 3-4) Logic to fetching the collection of records from the database.
Update Operation:
Let's implement the 'Update' operation endpoint.
Program.cs:
app.MapPut("/gadets/update", async (Gadgets gadgetToUpdate, MyWorldDbContext myWorldDbContext) => { var dbGadget = await myWorldDbContext.Gadgets.FindAsync(gadgetToUpdate.Id); if (dbGadget == null) { return Results.NotFound(); } dbGadget.Brand = gadgetToUpdate.Brand; dbGadget.Cost = gadgetToUpdate.Cost; dbGadget.ProductName = gadgetToUpdate.ProductName; dbGadget.Type = gadgetToUpdate.Type; await myWorldDbContext.SaveChangesAsync(); return Results.NoContent(); });
- (Line: 1) The 'MapPut' method represents the HTTP Put endpoint. The 'MapPut' method has 2 parameters like 1st parameter is 'URL' and 2nd parameter is the 'Delegate'. Here implemented Delegate as an asynchronous method that has 2 input parameters like 1st parameter payload to be updated and 2nd parameter injected the 'DatabaseContext'.
- (Line: 3) Fetching the existing data from the database.
- (Line: 4-7) Checking record trying to update is valid or not.
- (Line: 8-13) Updating and saving the record into the table.
Delete Operation:
Let's implement the 'Delete' operation endpoint.
Program.cs:
app.MapDelete("/gadgets/delete/{id}", async (int id, MyWorldDbContext myWorldDbContext) => { var dbGadgets = await myWorldDbContext.Gadgets.FindAsync(id); if (dbGadgets == null) { return Results.NoContent(); } myWorldDbContext.Gadgets.Remove(dbGadgets); await myWorldDbContext.SaveChangesAsync(); return Results.Ok(); });
- (Line: 1) The 'MapDelete' method represents the HTTP Delete endpoint. The 'MapDelete' method has 2 input parameters like 1st parameter is 'URL' and 2nd parameter is Delegate. Inside URL we can pass dynamic values with the '{}' expression, these values can be read into the Delegate handler method as input parameters.
- (Line: 3-7) Fetching the record that needs to be deleted.
- (Line: 8-10) Deleting the record from the database.
Finally, our entire Minimal API looks as below:
Program.cs:
using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddDbContext<MyWorldDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("MyWorldDbConnection")); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); // get endpoint app.MapGet("/gadgets", async (MyWorldDbContext myWorldDb) => { var gadgets = await myWorldDb.Gadgets.ToListAsync(); return Results.Ok(gadgets); }); // post endpoint app.MapPost("/gadgets/create", async (Gadgets gadgets, MyWorldDbContext myWorldDb) => { myWorldDb.Gadgets.Add(gadgets); await myWorldDb.SaveChangesAsync(); return Results.Ok(); }); // update endpoint app.MapPut("/gadets/update", async (Gadgets gadgetToUpdate, MyWorldDbContext myWorldDbContext) => { var dbGadget = await myWorldDbContext.Gadgets.FindAsync(gadgetToUpdate.Id); if (dbGadget == null) { return Results.NotFound(); } dbGadget.Brand = gadgetToUpdate.Brand; dbGadget.Cost = gadgetToUpdate.Cost; dbGadget.ProductName = gadgetToUpdate.ProductName; dbGadget.Type = gadgetToUpdate.Type; await myWorldDbContext.SaveChangesAsync(); return Results.NoContent(); }); // delete endpoint. app.MapDelete("/gadgets/delete/{id}", async (int id, MyWorldDbContext myWorldDbContext) => { var dbGadgets = await myWorldDbContext.Gadgets.FindAsync(id); if (dbGadgets == null) { return Results.NoContent(); } myWorldDbContext.Gadgets.Remove(dbGadgets); await myWorldDbContext.SaveChangesAsync(); return Results.Ok(); }); app.Run(); // Dbcontext public class MyWorldDbContext : DbContext { public MyWorldDbContext(DbContextOptions<MyWorldDbContext> options) : base(options) { } public DbSet<Gadgets> Gadgets { get; set; } } // Database classes public class Gadgets { public int Id { get; set; } public string ProductName { get; set; } public string Brand { get; set; } public decimal Cost { get; set; } public string Type { get; set; } }
Support Me!
Buy Me A Coffee
PayPal Me
Video Session:
Wrapping Up:
Hopefully, I think this article delivered some useful information on Minimal API CRUD Operations in .Net6 Application. I love to have your feedback, suggestions, and better techniques in the comment section below.
Comments
Post a Comment