Skip to content

Template for setting up .NET 9 web APIs with OpenAPI with TypeScript client codegen for Vue and React SPAs

Notifications You must be signed in to change notification settings

CharlieDigital/dn9-openapi-codegen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

.NET 9 OpenAPI + TypeScript Client Generation

A quick look at .NET 9's new OpenAPI tooling and how it compares to earlier versions of .NET using the swagger CLI tool (Swashbuckle.AspNetCore.Cli).

ℹ️ Fork or clone to play with this yourself and explore how it improves/digresses from Swashbuckle CLI

hot-reload-openapi-ts-gen.mp4

Layout:

/api-c              Controller API example
/api                Minimal API example
/openapi-spec-c     Controller API OpenAPI spec output target
/openapi-spec       Minimal API OpenAPI spec output target
/react-spa          React SPA generating a TypeScript client using the /api-c output
/vue-spa            Vue SPA generating a TypeScript client using the /api output

Setup the Project

# Create the workspace
mkdir dn9-openapi-codegen

# Create the .NET 9 web app
dn9-openapi-codgen
dotnet new webapi -minimal -f net9.0

# Create the SPA (Vue) or your framework of choice
cd ../
mkdir vue-spa
cd vue-spa
yarn create vite .

⚠️ IMPORTANT NOTE: Like the earlier Swashbuckle tooling, this new tooling starts the server to generate the OpenAPI spec. This means that your startup code will be invoked. Be aware of this if your startup code requires "active" components and replace it with a mock/stub that gets loaded/used when you see a flag (see the next section where we add an environment variable called GEN for this purpose to indicate that we are in a code generation context).

Setup the .NET Web API Project

Add the following package:

dotnet add package Microsoft.Extensions.ApiDescription.Server

Now update the .csproj file to include the following:

<!--
  api/api.csproj
-->
<!--
  This property group contains the directives for generating the
  OpenAPI specification.
-->
<PropertyGroup>
  <!-- The output directory (placed one level up in this case) -->
  <OpenApiDocumentsDirectory>../openapi-spec</OpenApiDocumentsDirectory>
  <!-- The file name -->
  <OpenApiGenerateDocumentsOptions>--file-name api-spec</OpenApiGenerateDocumentsOptions>
</PropertyGroup>

Now build and verify the /openapi-spec/api-spec.json file is created.

For more details, see this doc.

Now we can pull these into our front-end projects.

Configuring the Vue SPA

We'll use the Hey API package with Axios.

cd vue-spa
yarn add @hey-api/client-axios && yarn add @hey-api/openapi-ts -D

Then update the package.json to add our build command.

// vue-spa/package.json
"scripts": {
  "gen": "openapi-ts"
}

And now create a root level file openapi-ts.config.ts:

// vue-spa/openapi-ts.config.ts
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  client: '@hey-api/client-axios',
  input: '../openapi-spec/api-spec.json',
  output: 'src/api',
});

Now we can manually test generate a client

# vue-spa
yarn gen

Generate on Build

If we want to generate on build of our .NET project, we need to set up a hook in our .csproj

<!-- api/api.csproj -->

<!-- This section is a set of post-build commands -->
<Target Name="GenerateSpec" AfterTargets="Build" Condition="$(Configuration)=='Gen' Or $(GEN)=='true'">
  <Message Text="Generating OpenAPI schema file." Importance="high" />

  <!-- Generate TS bindings for the web app -->
  <Exec Command="yarn gen" WorkingDirectory="../vue-spa" />
</Target>

We trigger this manually using:

# macOS, Linux
GEN=true dotnet build

# macOS, Linux, Windows
dotnet build --configuration Gen

(Feel free to remove this constraint if you want it to always generate)

We can also make this work for hot reloads (see the video at the top):

# macOS, Linux
GEN=true dotnet watch build --non-interactive

# macOS, Linux, Windows
dotnet watch build --non-interactive --property:Configuration=Gen

For convenience, you might consider putting this into a script called _watch.sh.

Controller Based APIs

This also works more or less the same way with controller APIs:

# Make a new directory and project with the controller API
mkdir api-c
cd api-c
dotnet new webapi --use-controllers --no-https -f net9.0

# Add the project to the solution (for intellisense)
cd ../
dotnet sln add api-c

This example generates a client for the react-spa app.

Downsides

Big downside from earlier Swagger tooling is that there does not appear to be a way to automatically incorporate the XML document comments into the output schema.

This is accomplished by metadata attributes.

(Boooooo!)

This will probably be overcome in time by someone taking the initiative to create a transformer that will pull in descriptions.

About

Template for setting up .NET 9 web APIs with OpenAPI with TypeScript client codegen for Vue and React SPAs

Resources

Stars

Watchers

Forks