Reader small image

You're reading from  Web API Development with ASP.NET Core 8

Product typeBook
Published inApr 2024
PublisherPackt
ISBN-139781804610954
Edition1st Edition
Concepts
Right arrow
Author (1)
Xiaodi Yan
Xiaodi Yan
author image
Xiaodi Yan

Xiaodi Yan is a seasoned software engineer with a proven track record in the IT industry. Since 2015, he has been awarded Microsoft MVP, showcasing his dedication to and expertise in .NET, AI, DevOps, and cloud computing. He is also a Microsoft Certified Trainer (MCT), Azure Solutions Architect Expert, and LinkedIn Learning instructor. Xiaodi often presents at conferences and user groups, leveraging his extensive experience to engage and inspire audiences. Based in Wellington, New Zealand, he spearheads the Wellington .NET User Group, fostering a vibrant community of like-minded professionals. Connect with Xiaodi on LinkedIn to stay updated on his latest insights.
Read more about Xiaodi Yan

Right arrow

Introduction to minimal APIs

In the previous section, Creating a simple web API project, we created a simple web API project using the dotnet new webapi -n MyFirstApi -controllers command. The -controllers option (or --use-controllers) indicates that the project will use controller-based routing. Alternatively, the -minimal or --use-minimal-apis option can be used to create a project that uses minimal APIs. In this section, we will introduce minimal APIs.

Minimal APIs is a new feature introduced in ASP.NET Core 6.0. It is a new way to create APIs without using controllers. Minimal APIs are designed to be simple and lightweight with minimal dependencies. They are a good choice for small projects or prototypes, and also for projects that do not need the full features of controllers.

To create a minimal API project, we can use the following command:

dotnet new webapi -n MinimalApiDemo -minimal

There is no Controllers folder in the project. Instead, you can find the following code in the Program.cs file:

app.MapGet("/weatherforecast", () =>{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

The preceding code uses the MapGet() method to map the GET request to the /weatherforecast endpoint. The MapGet() method is an extension method of the IEndpointRouteBuilder interface. This interface is used to configure the endpoints in the application. Its extension method, MapGet(), returns an IEndpointConventionBuilder interface that allows us to use fluent APIs to configure the endpoint by using other extension methods, such as WithName() and WithOpenApi(). The WithName() method is used to set the name of the endpoint. The WithOpenApi() method is used to generate an OpenAPI document for the endpoint.

Creating a simple endpoint

Let us create a new /posts endpoint that supports CRUD operations. First, add the following code to the end of the Program.cs file to define a Post class:

public class Post{
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Content { get; set; } = string.Empty;
}

Add the following code to the Program.cs file:

var list = new List<Post>(){
    new() { Id = 1, Title = "First Post", Content = "Hello World" },
    new() { Id = 2, Title = "Second Post", Content = "Hello Again" },
    new() { Id = 3, Title = "Third Post", Content = "Goodbye World" },
};
app.MapGet("/posts",
    () => list).WithName("GetPosts").WithOpenApi().WithTags("Posts");
app.MapPost("/posts",
    (Post post) =>
    {
        list.Add(post);
        return Results.Created($"/posts/{post.Id}", post);
    }).WithName("CreatePost").WithOpenApi().WithTags("Posts");
app.MapGet("/posts/{id}", (int id) =>
{
    var post = list.FirstOrDefault(p => p.Id == id);
    return post == null ? Results.NotFound() : Results.Ok(post);
}).WithName("GetPost").WithOpenApi().WithTags("Posts");
app.MapPut("/posts/{id}", (int id, Post post) =>
{
    var index = list.FindIndex(p => p.Id == id);
    if (index == -1)
    {
        return Results.NotFound();
    }
    list[index] = post;
    return Results.Ok(post);
}).WithName("UpdatePost").WithOpenApi().WithTags("Posts");
app.MapDelete("/posts/{id}", (int id) =>
{
    var post = list.FirstOrDefault(p => p.Id == id);
    if (post == null)
    {
        return Results.NotFound();
    }
    list.Remove(post);
    return Results.Ok();
}).WithName("DeletePost").WithOpenApi().WithTags("Posts");

The preceding code defines five endpoints:

  • GET /posts: Get all posts
  • POST /posts: Create a new post
  • GET /posts/{id}: Get a post by ID
  • PUT /posts/{id}: Update a post by ID
  • DELETE /posts/{id}: Delete a post by ID

We use the WithTags extension method to group these endpoints into a tag named Posts. In this example, a list is used to store the posts. In a real-world application, we should use a database to store the data.

Using DI in minimal APIs

Minimal APIs support DI as well. You can find the IPostService interface and its PostService implementation in the Services folder. Here is an example of using DI in minimal APIs:

app.MapGet("/posts", async (IPostService postService) =>{
    var posts = await postService.GetPostsAsync();
    return posts;
}).WithName("GetPosts").WithOpenApi().WithTags("Posts");
app.MapGet("/posts/{id}", async (IPostService postService, int id) =>
{
    var post = await postService.GetPostAsync(id);
    return post == null ? Results.NotFound() : Results.Ok(post);
}).WithName("GetPost").WithOpenApi().WithTags("Posts");
app.MapPost("/posts", async (IPostService postService, Post post) =>
{
    var createdPost = await postService.CreatePostAsync(post);
    return Results.Created($"/posts/{createdPost.Id}", createdPost);
}).WithName("CreatePost").WithOpenApi().WithTags("Posts");
app.MapPut("/posts/{id}", async (IPostService postService, int id, Post post) =>
{
    try
    {
        var updatedPost = await postService.UpdatePostAsync(id, post);
        return Results.Ok(updatedPost);
    }
    catch (KeyNotFoundException)
    {
        return Results.NotFound();
    }
}).WithName("UpdatePost").WithOpenApi().WithTags("Posts");
app.MapDelete("/posts/{id}", async (IPostService postService, int id) =>
{
    try
    {
        await postService.DeletePostAsync(id);
        return Results.NoContent();
    }
    catch (KeyNotFoundException)
    {
        return Results.NotFound();
    }
}).WithName("DeletePost").WithOpenApi().WithTags("Posts");

In the preceding code, the IPostService interface is used as a parameter of the action method. The DI container will inject the correct implementation into the action method. You can run the project and test the endpoints. It should have the same behavior as the controller-based project.

What is the difference between minimal APIs and controller-based APIs?

Minimal APIs are simpler than controller-based APIs, allowing us to map endpoints to methods directly. This makes minimal APIs a good choice for quickly creating simple APIs or demo projects. However, minimal APIs do not support the full range of features that controllers provide, such as model binding, model validation, and so on. These features may be added in the future. Therefore, we will mainly use controller-based APIs and not discuss minimal APIs in detail in this book. If you want to learn more about minimal APIs, please refer to the official documentation at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis.

Previous PageNext Page
You have been reading a chapter from
Web API Development with ASP.NET Core 8
Published in: Apr 2024Publisher: PacktISBN-13: 9781804610954
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Xiaodi Yan

Xiaodi Yan is a seasoned software engineer with a proven track record in the IT industry. Since 2015, he has been awarded Microsoft MVP, showcasing his dedication to and expertise in .NET, AI, DevOps, and cloud computing. He is also a Microsoft Certified Trainer (MCT), Azure Solutions Architect Expert, and LinkedIn Learning instructor. Xiaodi often presents at conferences and user groups, leveraging his extensive experience to engage and inspire audiences. Based in Wellington, New Zealand, he spearheads the Wellington .NET User Group, fostering a vibrant community of like-minded professionals. Connect with Xiaodi on LinkedIn to stay updated on his latest insights.
Read more about Xiaodi Yan