Generates Controllers, DTOs and MediatR Requests from a given OpenAPI Spec file to support API First development. Business logic implementation is handled by MediatR handlers that implement the generated MediatR Requests.
Code is generated using a Roslyn based Source Generator. To find out more about Roslyn Source Generators go here: https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview
Currently supports ASP.NET Core 6.0, 7.0 and 8.0, as well as OpenAPI Spec versions 3 and 2 in both yaml and json formats.
dotnet add package ApiFirstMediatR.Generator
Register your OpenAPI spec file by adding the following to your .csproj
:
<ItemGroup>
<!-- Registers the OpenAPI spec -->
<AdditionalFiles Include="api_spec.json" />
</ItemGroup>
Hello World OpenAPI spec:
openapi: 3.0.1
info:
title: HelloWorld API
version: v1
paths:
/api/HelloWorld:
get:
tags:
- HelloWorld
operationId: GetHelloWorld
description: Gets a HelloWorld Message
parameters: []
responses:
200:
description: Hello world!
content:
application/json:
schema:
$ref: '#/components/schemas/HelloWorldDto'
components:
schemas:
HelloWorldDto:
type: object
properties:
message:
type: string
nullable: true
security: []
The source generators will then generate the following based on he given OpenAPI spec file:
// <auto-generated/>
using System.Text.Json.Serialization;
namespace compilation.Dtos
{
public class HelloWorldDto
{
[JsonPropertyName("message")]
public string? Message { get; set; }
}
}
// <auto-generated/>
#nullable enable
using MediatR;
using compilation.Dtos;
namespace compilation.Requests
{
/// <summary>
/// Gets a HelloWorld Message
/// </summary>
/// <returns>Hello world!</returns>
public sealed class GetHelloWorldQuery : IRequest<HelloWorldDto>
{
public GetHelloWorldQuery()
{
}
}
}
// <auto-generated/>
#nullable enable
using MediatR;
using Microsoft.AspNetCore.Mvc;
using compilation.Dtos;
using compilation.Requests;
namespace compilation.Controllers
{
public sealed class ApiController : Controller
{
private readonly IMediator _mediator;
public ApiController(IMediator mediator)
{
_mediator = mediator;
}
/// <summary>
/// Gets a HelloWorld Message
/// </summary>
/// <returns>Hello world!</returns>
[HttpGet("/api/HelloWorld")]
public async Task<ActionResult> GetHelloWorld(CancellationToken cancellationToken)
{
var request = new GetHelloWorldQuery();
var response = await _mediator.Send(request, cancellationToken);
return Ok(response);
}
}
}
To implement the Hello World endpoint create the following handler:
using HelloWorld.Dtos;
using HelloWorld.Requests;
using MediatR;
namespace HelloWorld.Handlers
{
public sealed class GetHelloWorldQueryHandler : IRequestHandler<GetHelloWorldQuery, HelloWorldDto>
{
public Task<HelloWorldDto> Handle(GetHelloWorldQuery query, CancellationToken cancellationToken)
{
// Endpoint implementation goes here
}
}
}
In the solution explorer expand Project -> Dependencies -> Analyzers -> ApiFirstMediatR.Generator -> ApiFirstMediatR.Generator.ApiSourceGenerator.
In the explorer expand Project -> Dependencies -> .NET 6.0 -> Source Generators -> ApiFirstMediatR.Generator.ApiSourceGenerator
Add the following to your .csproj
<!-- Begin VSCode Compatibility -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
</ItemGroup>
<Target Name="CleanSourceGeneratedFiles" BeforeTargets="BeforeRebuild" DependsOnTargets="$(BeforeBuildDependsOn)">
<RemoveDir Directories="$(CompilerGeneratedFilesOutputPath)" />
</Target>
<!-- End VSCode Compatibility -->
This will force the generators to output the generated files to the Generated
directory, but notify the compiler to ignore the generated files and continue to use the normal Roslyn Source Generator compile process. Adding the Generated directory to your .gitignore
is recommended.
Available MSBuild properties:
Property | Default | Available Options | Description |
---|---|---|---|
ApiFirstMediatR_SerializationLibrary | System.Text.Json | System.Text.Json, Newtonsoft.Json | Serialization Library that the generated code should use. |
ApiFirstMediatR_RequestBodyName | Body | string | The name that's used for request bodies in mediatr requests. |
To set an MSBuild option you need to add the property and value to your csproj file.
Example:
<PropertyGroup>
<ApiFirstMediatR_SerializationLibrary>Newtonsoft.Json</ApiFirstMediatR_SerializationLibrary>
</PropertyGroup>