RSCG – immediate.apis
| name | immediate.apis |
| nuget | https://www.nuget.org/packages/immediate.apis/ |
| link | https://github.com/immediateplatform/immediate.apis |
| author | Stuart Turner |
Defining APIs in classes instead of in minimal API or controllers
This is how you can use immediate.apis .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Immediate.Apis" Version="1.3.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
The code that you will use is
using APIDemo;
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.AddAPIDemoHandlers();
var app = builder.Build();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.MapAPIDemoEndpoints();
//app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
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();
app.Run();
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
using Immediate.Apis.Shared;
using Immediate.Handlers.Shared;
using Microsoft.AspNetCore.Http.HttpResults;
namespace APIDemo;
[Handler]
[MapGet("/users")]
public static partial class PersonAPI
{
public record Query;
private static async ValueTask<Person[]> HandleAsync(
Query _,
CancellationToken token)
{
await Task.Delay(1000);
return new[] { new Person { FirstName = "Ignat", LastName = "Andrei" } };
}
}
namespace APIDemo;
public class Person
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
The code that is generated is
using System.Threading;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
#pragma warning disable CS1591
namespace Microsoft.AspNetCore.Builder
{
public static partial class APIDemoRoutesBuilder
{
private static void MapAPIDemo_PersonAPIEndpoint(IEndpointRouteBuilder app)
{
var endpoint = app
.MapGet(
"/users",
async (
[AsParameters] global::APIDemo.PersonAPI.Query parameters,
[FromServices] global::APIDemo.PersonAPI.Handler handler,
CancellationToken token
) =>
{
var ret = await handler.HandleAsync(parameters, token);
return ret;
}
);
}
}
}
namespace APIDemo
{
/// <remarks><see cref="global::APIDemo.PersonAPI.Query" /> registered using <c>[AsParameters]</c></remarks>
partial class PersonAPI;
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
#pragma warning disable CS1591
namespace Microsoft.AspNetCore.Builder;
public static partial class APIDemoRoutesBuilder
{
public static IEndpointRouteBuilder MapAPIDemoEndpoints(
this IEndpointRouteBuilder app
)
{
MapAPIDemo_PersonAPIEndpoint(app);
return app;
}
}
using Microsoft.Extensions.DependencyInjection;
#pragma warning disable CS1591
namespace APIDemo;
partial class PersonAPI
{
public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler<global::APIDemo.PersonAPI.Query, global::APIDemo.Person[]>
{
private readonly global::APIDemo.PersonAPI.HandleBehavior _handleBehavior;
public Handler(
global::APIDemo.PersonAPI.HandleBehavior handleBehavior
)
{
var handlerType = typeof(PersonAPI);
_handleBehavior = handleBehavior;
}
public async global::System.Threading.Tasks.ValueTask<global::APIDemo.Person[]> HandleAsync(
global::APIDemo.PersonAPI.Query request,
global::System.Threading.CancellationToken cancellationToken = default
)
{
return await _handleBehavior
.HandleAsync(request, cancellationToken)
.ConfigureAwait(false);
}
}
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior<global::APIDemo.PersonAPI.Query, global::APIDemo.Person[]>
{
public HandleBehavior(
)
{
}
public override async global::System.Threading.Tasks.ValueTask<global::APIDemo.Person[]> HandleAsync(
global::APIDemo.PersonAPI.Query request,
global::System.Threading.CancellationToken cancellationToken
)
{
return await global::APIDemo.PersonAPI
.HandleAsync(
request
, cancellationToken
)
.ConfigureAwait(false);
}
}
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public static IServiceCollection AddHandlers(
IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
{
services.Add(new(typeof(global::APIDemo.PersonAPI.Handler), typeof(global::APIDemo.PersonAPI.Handler), lifetime));
services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler<global::APIDemo.PersonAPI.Query, global::APIDemo.Person[]>), typeof(global::APIDemo.PersonAPI.Handler), lifetime));
services.Add(new(typeof(global::APIDemo.PersonAPI.HandleBehavior), typeof(global::APIDemo.PersonAPI.HandleBehavior), lifetime));
return services;
}
}
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
#pragma warning disable CS1591
namespace APIDemo;
public static class HandlerServiceCollectionExtensions
{
public static IServiceCollection AddAPIDemoBehaviors(
this IServiceCollection services)
{
return services;
}
public static IServiceCollection AddAPIDemoHandlers(
this IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Scoped
)
{
global::APIDemo.PersonAPI.AddHandlers(services, lifetime);
return services;
}
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/immediate.apis