Generating TypeScript client from .NET 9 API with OpenAPI and Orval
Alex Khanuckaev

Alex Khanuckaev @alechka

About: Fullstack developer

Location:
Tel Aviv, Israel
Joined:
Jan 10, 2025

Generating TypeScript client from .NET 9 API with OpenAPI and Orval

Publish Date: May 13
0 0

A step-by-step guide on how to automatically create strongly typed TypeScript client for your .NET API service.

Creating Demo API

First, let's demonstrate how to create an API. All examples are provided using console utilities, but they can be reproduced using IDE of choice.

Let's create a solution for our application:

dotnet new sln - name OpenApiDemo
Enter fullscreen mode Exit fullscreen mode

Creating a full-scale WebAPI project with controllers:

dotnet new webapi -use-controllers -n DemoApi
Enter fullscreen mode Exit fullscreen mode

And let's add it to our solution:

dotnet sln add DemoApi
Enter fullscreen mode Exit fullscreen mode

As a result, you will have file structure like this:
Image description

Adding OpenAPI and Scalar

Recently, Microsoft introduced their own API description generator, reducing the reliance on Swashbuckle Swagger. Although this decision generated some controversy, considering the recent commercialization of many free libraries such as MassTransit and AutoMapper, it may not be entirely unfavorable. It's 2025 after all, so no need to depend on swagger.

So, let's add an OpenApi package to our dotnet project:

dotnet add DemoApi package Microsoft.AspNetCore.OpenApi
Enter fullscreen mode Exit fullscreen mode

And also let's add Scalar to test our API (it's not actually needed to create typescript client, but it's always nice to have).
dotnet add DemoApi package Scalar.AspNetCore

And, also, we need to setup scalar to communicate with openapi generated references:

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference();
}
Enter fullscreen mode Exit fullscreen mode

Let's run our API and see if everything is OK:

dotnet run --project DemoApi
Enter fullscreen mode Exit fullscreen mode

Image description

Generating OpenAPI reference file on build

Fine! Now we need to get api description file on build. To do this we need to install Microsoft.Extensions.ApiDescription.Server package by following command:

dotnet add DemoApi package Microsoft.Extensions.ApiDescription.Server
Enter fullscreen mode Exit fullscreen mode

Ok, let's build project

dotnet build DemoApi
Enter fullscreen mode Exit fullscreen mode

After building there should be a file DemoApi.json inside obj folder of your project

Image description

Regrettably, the DemoApi.json file is generated exclusively within the obj folder. For those utilizing a CI/CD pipeline where the backend and frontend are built in separate steps, and the output from the backend build is limited to the bin folder or, in some cases, only the docker image. 

There are two potential solutions: either copy this file during the CI/CD step or modify your .csproj file accordingly. Given that MSBuild can be complex, here is the code that needs to be added:

<Target Name="PostBuild" AfterTargets="Build">
      <Copy SourceFiles="$(ProjectDir)obj\DemoAPI.json" DestinationFolder="$(OutDir)" />
      <Message Text="open api file copiied to $(OutDir)" Importance="high"/>
  </Target>

  <Target Name="CopyFilesToPublish" AfterTargets="Publish">
      <Copy SourceFiles="$(OutDir)\DemoAPI.json" DestinationFolder="$(PublishDir)"/>
  </Target>
Enter fullscreen mode Exit fullscreen mode

Command to test those adjustments:

dotnet publish DemoApi -o out
Enter fullscreen mode Exit fullscreen mode

Image description

Front-end

Front-end Preparations:

We will be using orval to generate our client, primarily because it comes highly recommended by my front-end coworkers.

Some preparational steps:

mkdir Front
cd Front
npm init
npm i orval -D
npm i axios
Enter fullscreen mode Exit fullscreen mode

TypeScript client generation:

Create orval.config.js (this one generates client that uses axios library to make calls. If you want to use fetch api see documentation):

module.exports = {
  weather: {
    input: {
      target: "../out/DemoAPI.json",
    },
    output: {
      mode: "split",
      target: "endpoint.ts",
      schemas: "model",
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

To generate your typescript client, use command:

node .\node_modules\orval\dist\bin\orval.js --config .\orval.config.js
Enter fullscreen mode Exit fullscreen mode

That's it. Your typescript client file is in endpoint.ts, and types for API contract calls are in models folder.

Image description

If you need a source code for this tutorial, I had created a github repository.

Btw, you can subscribe to my medium blog, to get my posts faster.

Comments 0 total

    Add comment