This project uses roslyn to create an API from open api specification. View a post on the idea behind this project here.
This ensures that the application is always returning models that match the defined API specification.
The easiest way to describe what the project does is through an example of what is generated:
For the following yaml
openapi: 3.0.1
paths:
/api/Todo:
get:
tags:
- Todo
operationId: ApiTodoGet
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ToDoItem'
components:
schemas:
ToDoItem:
type: object
properties:
id:
type: integer
format: int32
name:
type: string
nullable: true
isCompleted:
type: boolean
A controller, model and interface are generated.
Controller:
[ApiController]
[Route("/api/Todo")]
public class ApiTodo : ControllerBase
{
private readonly IGetApiTodoInteractor _getApiTodoInteractor;
public ApiTodo(IGetApiTodoInteractor getApiTodoInteractor)
{
_getApiTodoInteractor = getApiTodoInteractor;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var result = await _getApiTodoInteractor.Execute();
return Ok(result);
}
}
Model:
public record ToDoItem
{
[JsonPropertyName("id")]
public int? Id { get; init; }
[JsonPropertyName("name")]
public string? Name { get; init; }
[JsonPropertyName("isCompleted")]
public bool? IsCompleted { get; init; }
}
Interface:
public interface IGetApiTodoInteractor
{
Task<ToDoItem[]> Execute();
}
This can either be implemented or use the AutoFixture implementation, to create a generated response:
public class GetApiTodoInteractor : IGetApiTodoInteractor
{
private readonly Fixture _fixture = new Fixture();
public async Task<ToDoItem[]> Execute()
{
return _fixture.Create<ToDoItem[]>();
}
}
Generated files for definition.yaml can be found here
This can then be implemented in the project with any custom logic, e.g..
The above examples are from the example project generated by the definition file in the root of the project. All of the generated files are in the generated folder in that project, this folder is deleted and recreated on each run.
Running dotnet run --project example
and navigating to http://localhost:5009/api/todo
produces the following response:
There are two available projects OpenApiSpecGeneration.ApiGeneration and OpenApiSpecGeneration.ApiGeneration.Console.
The first can be used as a package (soon) and the second is a console app that takes an input file and produces c# files to the gievn output directory. See the project folder for more details on usage.
Uses Microsoft.OpenApi models and reader and so JSON and YAML open api specs are supported through that library.
The console app takes an input json openapi spec and outputs C# files to the given output directory.