Minimal Web API With .Net 8

Before we start, the code for this article is on github here.

What is REST API?

The term REST stands for REpresentational State Transfer. It is an architectural style that defines a set of rules to create Web Services. In a client-server communication, REST suggests creating an object of the data requested by the client and send the values of the object in response to the user. For example, if the user is requesting for cab booking in Bangalore at a certain place and time, then you can create an object on the server-side. So, over here, you have an object, and you are sending the state of an object. Therefore, REST is known as Representational State Transfer.

The architectural style of REST helps in leveraging the lesser use of bandwidth to make an application more suitable for the internet. It is often regarded as the “language of the internet” and is completely based on the resources.

Principles of REST API

Below are the six guiding principles of REST:

Stateless

The URL is used to uniquely identify the resource and the body holds the state of the requesting resource. Once the server processes the request, a response is sent to the client through body, status, or headers. The requests sent from a client to a server will contain all the required information to make the server understand the requests sent from the client. This can be either a part of URL, query-string parameters, body, or even headers. No state is cached in the server API so every request is agnostic of each other. This behavior of REST also helps in scaling the API service in cloud environment.

Client-Server

The client-server architecture enables a uniform interface and separates clients from the servers. This enhances the portability across multiple platforms as well as the scalability of the server components.

Uniform Interface

To obtain the uniformity throughout the application, REST has the following four interface constraints:

  • Resource identification
  • Resource Manipulation using representations
  • Self-descriptive messages
  • Hypermedia as the engine of application state

Cacheable

To provide a better performance, the applications are often made cacheable. This is done by labeling the response from the server as cacheable or non-cacheable either implicitly or explicitly. If the response is denied as cacheable, then the client cache can reuse the response data for equivalent responses in the future.

Minimal APIs in .Net 8 or .Net 7

Minimal APIs are architected to create HTTP APIs with minimal dependencies. They are ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core.

Limitations of Minimal API

  1. No support for filters: For example, no support for IAsyncAuthorizationFilter, IAsyncActionFilter, IAsyncExceptionFilter, IAsyncResultFilter, and IAsyncResourceFilter.
  2. No support for model binding, i.e. IModelBinderProvider, IModelBinder. Support can be added with a custom binding shim.
  3. No support for binding from forms. This includes binding IFormFile. We plan to add support for IFormFile in the future.
  4. No built-in support for validation, i.e. IModelValidator
  5. No support for application parts or the application model. There's no way to apply or build your own conventions.
  6. No built-in view rendering support. We recommend using Razor Pages for rendering views.
  7. No support for JsonPatch
  8. No support for OData
  9. No support for ApiVersioning. See this issue for more details.

To demonstrate the minimal API in .net 6 I have created a sample here,

With the following APIs,

RESTFull Minimal Web API with .Net 6

REST APIs follow standard HTTP Verbs like GET, POST, PUT, DELETE, PATCH which are basically CRUD operation on an object. The APIs are arranged to form an internet resource. For example in the above example, we have resource as “todoitem” which can be created, modified, deleted using APIs, and URL format is formed accordingly.

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 < TodoDb > (opt => opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.MapGet("/", () => "Hello World!");
app.MapGet("/todoitems", async (TodoDb db) => await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) => await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) => await db.Todos.FindAsync(id)
    is Todo todo ? Results.Ok(todo) : Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) => {
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($ "/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) => {
    var todo = await db.Todos.FindAsync(id);
    if (todo is null) return Results.NotFound();
    todo.Name = inputTodo.Name;
    todo.IsComplete = inputTodo.IsComplete;
    await db.SaveChangesAsync();
    return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) => {
    if (await db.Todos.FindAsync(id) is Todo todo) {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(todo);
    }
    return Results.NotFound();
});
app.Run();
class Todo {
    public int Id {
        get;
        set;
    }
    public string ? Name {
        get;
        set;
    }
    public bool IsComplete {
        get;
        set;
    }
}
class TodoDb: DbContext {
    public TodoDb(DbContextOptions < TodoDb > options): base(options) {}
    public DbSet < Todo > Todos => Set < Todo > ();
}

Conclusion

REST architecture style provides a standard way to arrange resources over internet and a common way for clients to access and get the server data. Minimal API requires minimum code and quick and easy way to create APIs which do not require Auth or which sits behind a gateway(with Auth) and has very minimal dependencies.

References

  1. https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-8.0&tabs=visual-studio
  2. https://restfulapi.net/