.NET 7 Preview 4
is released and it includes some nice features related to ASP.NET Core Minimal
APIs. One of them is the support for self-describing API endpoints.
In this
post, let's have a look at how it works.
Consider the below Minimal API endpoints prior to .NET 7 Preview 4.
app.MapGet("/employees", async (EmployeeContext dbContext) =>
{
return Results.Ok(await dbContext.Employees.ToListAsync());
});
Now if we have a look at the Swagger document, I can see something like this.
|
GET: /employees |
It only says the endpoint returns 200, but nothing about the response type.
Let's have a look at another example. Consider the below endpoint.
app.MapGet("/employees/{id}", async (int id, EmployeeContext dbContext) =>
{
Employee employee = await dbContext.Employees.FindAsync(id);
if (employee is null)
{
return Results.NotFound();
}
return Results.Ok(employee);
});
And this would appear in the Swagger document as follows.
|
GET: /employees/{id}
|
Again nothing about the Response Type, and obviously no sign about the
endpoint returning 404.
If we are to enrich these missing details, we will have to update the code
as follows.
app
.MapGet("/employees", async (EmployeeContext dbContext) =>
{
return Results.Ok(await dbContext.Employees.ToListAsync());
})
.Produces<List<Employee>>();
app
.MapGet("/employees/{id}", async (int id, EmployeeContext dbContext) =>
{
Employee employee = await dbContext.Employees.FindAsync(id);
if (employee is null)
{
return Results.NotFound();
}
return Results.Ok(employee);
})
.Produces<Employee>()
.Produces(StatusCodes.Status404NotFound);
And now we can see the Swagger document is updated.
|
GET: /employees |
|
GET: /employees/{id}
|
But what if we can let the APIs describe themselves without adding additional
annotations.
With .NET 7 Preview 4, I can change the above endpoints as follows.
app.MapGet("/employees", async (EmployeeContext dbContext) =>
{
return TypedResults.Ok(await dbContext.Employees.ToListAsync());
});
This will describe the endpoint the same way it did with annotations.
The only change I did here is use the new
TypedResults factory class instead of
Results
factory class when generating the result. The new TypedResults factory class will create Typed results (as the name suggests of
course) instead of
IResult as it did with Results factory class. And all these Typed results implement a new interface
IEndpointMetadataProvider.
public interface IEndpointMetadataProvider
{
static abstract void PopulateMetadata(EndpointMetadataContext context);
}
The framework will call PopulateMetadata() when the endpoint is built
and that adds the necessary endpoint metadata to describe the HTTP response
type.
Now when we have multiple return types, we need to explicitly specify the
return types as follows.
app.MapGet("/employees/{id}", async Task<Results<Ok<Employee>, NotFound>> (int id, EmployeeContext dbContext) =>
{
Employee employee = await dbContext.Employees.FindAsync(id);
if (employee is null)
{
return TypedResults.NotFound();
}
return TypedResults.Ok(employee);
});
And this also will describe the endpoint the same way it did with
annotations.
You can find the complete sample code here.
https://github.com/jaliyaudagedara/minimal-api
More Read
ASP.NET Core updates in .NET 7 Preview 4
Hope this helps.
Happy Coding.
Regards,
Jaliya