Minimal APIs in .NET 6 – KLCWEB

In this article, we will clarify the center thought and essential ideas of the negligible APIs in .NET 6. In any case, assuming we attempt to clarify it in one sentence, it will be that it is an API without the requirement for a regulator.

Other than a hypothetical clarification, we will plunge into the code and show how we can execute a negligible API that has all CRUD tasks.

The Origin of the Minimal APIs

The tale of the insignificant API began in November 2019. The designer local area got an opportunity to see the execution of the conveyed number cruncher in Go, Python, C#, and Javascript. Whenever the local area began looking at the number of documents and lines of code that are expected to do practically exactly the same thing with C# contrasted with different dialects, it was evident that C# appears to be more confounded than most of them.

Envision the number of ideas and highlights collected throughout the long term and how overpowering it very well may be for a novice to dive into the universe of .NET web advancement. Thusly, a .NET Core group needed to diminish the intricacy for all engineers (newbies and veterans) and embrace moderation. So assuming that we will make a straightforward API with a solitary endpoint, we should have the option to do it inside a solitary record. In any case, assuming we want to switch later to utilize regulators once more, we should likewise have the option to do that.

How to Setup Minimal APIs?

We really want to have Visual Studio 2022 with the ASP.NET and web advancement responsibility to track with this article.

To make an insignificant API, we will make a C# project from the ASP.NET Core Empty layout and uncheck all the checkboxes in the extra data discourse. Doing that, we will wind up with the Program class with four lines in it:

Finally, with the app.Run() strategy, we can run our application.

var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet(“/”, () => “Hello World!”); app.Run();

And that’s it. Once we run our app, we will see the Hello Word! message in a browser.

We should clarify how it is feasible to have an API with one endpoint ready for action with four lines of code.

The primary thing we can see is missing Run mandates. C#10 presented worldwide Run mandates, and the normal ones are incorporated of course in the event that the element is empowered. Since one of them is Microsoft.AspNetCore.Builder, we don’t have to compose anything.

Then, at that point, we can see MapGet, an augmentation strategy from the EndpointRouteBuilderExtensions class that acknowledges a representative as one of the boundaries. Tolerating any representative is another model where C#10 put negligible API at its ideal. We can pass a strategy to the MapGet technique, and the compiler will put forth a valiant effort to sort out some way to change it over to the RequestDelegate. On the off chance that it can’t, it will tell us.

How Does Dependency Injection Work With the Minimal APIs?

Another component in the reliance infusion (DI) holder in the .NET 6 empowers us to realize which type is enlisted as a resolvable sort in the compartment. That implies we can revise a representative in the MapGet technique for certain sorts that we have enrolled with the DI without the requirement for extra ascribes or infusions through constructors. For instance, we can compose:

app.MapGet(“/”, (IHttpClientFactory httpClientFactory) => “Hello World!”));

Furthermore, the system will realize that IHttpClientFactory is enlisted as a resolvable sort. It can visit the DI holder and populate it with the enlisted type. This was unrealistic previously .NET 6.

Implementation of the CRUD Methods in the Minimal APIs

For this model, we will involve the Entity Framework Core in-memory information base. You can observe a point-by-point arrangement in the Creating Multiple Resources with a Single Request in the ASP.NET Core article.

Since we will work on articles, how about we make an Article class:

public class Article { public int Id { get; set; } public string? Title { get; set; } public string? Content { get; set; } public DateTime? PublishedAt { get; set; } }

And an ArticleRequest record:

public record ArticleRequest(string? Title, string? Content, DateTime? PublishedAt);

Let’s first implement get methods and explain what’s happening:

app.MapGet(“/articles”, async (ApiContext context) => Results.Ok(await context.Articles.ToListAsync())); app.MapGet(“/articles/{id}”, async (int id, ApiContext context) => { var article = await context.Articles.FindAsync(id); return article != null ? Results.Ok(article) : Results.NotFound(); });

For the two strategies, we add the course design as a first boundary. In the primary MapGet execution ApiContext is settled in the agent since it is enrolled as a resolvable kind. In the second MapGet execution, we add id as an extra boundary in the representative. We could likewise change the request for the boundaries:

app.MapGet(“/articles/{id}”, async (ApiContext context, int id) => { var article = await context.Articles.FindAsync(id); return article != null ? Results.Ok(article) : Results.NotFound(); });

What’s more all that will keep on working. That will be that clever component where the compiler attempts to determine any agent as a RequestDelegate, and it is doing very steady employment.

To proceed, how about we carry out POST and DELETE techniques

app.MapPost(“/articles”, async (ArticleRequest article, ApiContext context) => { var createdArticle = context.Articles.Add(new Article { Title = article.Title ?? string.Empty, Content = article.Content ?? string.Empty, PublishedAt = article.PublishedAt, }); await context.SaveChangesAsync(); return Results.Created($”/articles/{createdArticle.Entity.Id}”, createdArticle.Entity); }); app.MapDelete(“/articles/{id}”, async (int id, ApiContext context) => { var article = await context.Articles.FindAsync(id); if (article == null) { return Results.NotFound(); } context.Articles.Remove(article); await context.SaveChangesAsync(); return Results.NoContent(); });

Finally, we are going to implement the PUT method:

app.MapPut(“/articles/{id}”, async (int id, ArticleRequest article, ApiContext context) => { var articleToUpdate = await context.Articles.FindAsync(id); if (articleToUpdate == null) return Results.NotFound(); if (article.Title != null) articleToUpdate.Title = article.Title; if (article.Content != null) articleToUpdate.Content = article.Content; if (article.PublishedAt != null) articleToUpdate.PublishedAt = article.PublishedAt; await context.SaveChangesAsync(); return Results.Ok(articleToUpdate); });

Since we need to focus on Minimal APIs our execution is basic and it is missing appropriate solicitation model approvals or utilizing planning with AutoMapper. You can peruse how to apply every one of these appropriately in our ASP.NET Core Web API – Post, Put, Delete article.

Curiously, there isn’t an augmentation technique MapPatch in the EndpointRouteBuilderExtensions class. Yet, we can utilize the MapMethods technique that is more vigorous and versatile than the past ones:

app.MapMethods(“/articles/{id}”, new[]{ “PATCH” }, async (int id, ArticleRequest article, ApiContext context) =>{ … });

To carry out the PATCH technique in the correct manner, you can peruse more with regards to it in our Using HttpClient to Send HTTP PATCH Requests in the ASP.NET Core article.

How to Use Swagger, Authentication, and Authorization?

Interestingly, there isn’t any genuine contrast in how to set up and involve Swagger in the Minimal APIs than previously. You can peruse more with regards to Swagger, and how to arrange it in our Configuring and Using Swagger UI in ASP.NET Core Web API article.

The equivalent goes for confirmation and approval. The main new component is adding the verification and approval ascribes (or any property) to the representative techniques. That was impractical in the more seasoned variants of the C#. So assuming that we would execute verification as in our ASP.NET Core Authentication with JWT article, we could add [Authorize] trait on our agents:

app.MapPut(“/articles/{id}”, [Authorize] async (int id, ArticleRequest article, ApiContext context) =>{}

Organizing the Code in Minimal APIs

With insignificant APIs, the Program class can turn out to be very enormous with a ton of code lines. To keep away from that, we should show how we can coordinate our code.

We will extricate the code inside each planning technique into a different ArticleService class that will carry out the IArticleService interface (you can observe the execution in our source code). And afterward, since we can infuse our administration into delegate techniques we can change our code to:

var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase(“api”)); builder.Services.AddScoped(); var app = builder.Build(); app.MapGet(“/articles”, async (IArticleService articleService) => await articleService.GetArticles()); app.MapGet(“/articles/{id}”, async (int id, IArticleService articleService) => await articleService.GetArticleById(id)); app.MapPost(“/articles”, async (ArticleRequest articleRequest, IArticleService articleService) => await articleService.CreateArticle(articleRequest)); app.MapPut(“/articles/{id}”, async (int id, ArticleRequest articleRequest, IArticleService articleService) => await articleService.UpdateArticle(id, articleRequest)); app.MapDelete(“/articles/{id}”, async (int id, IArticleService articleService) => await articleService.DeleteArticle(id)); app.Run();

Our Program class looks more coordinated at this point. We could additionally extricate all planning calls to a different expansion strategy, however with each refactor, we are wandering from the first thought of the negligible APIs to be direct.


In this article, we’ve talked about minimal API origin and its motivation to exist. We also have shown how to create minimal API with CRUD operations. 

Tagged : /