Skip to content

Commit

Permalink
Kiota: Replace PowerShell script with inline MSBuild task for improve…
Browse files Browse the repository at this point in the history
…d performance (#1696)

* Kiota: Replace PowerShell script with inline MSBuild task for improved performance

* Update kiota and docs
  • Loading branch information
bkoelman authored Mar 2, 2025
1 parent 749e588 commit 3356544
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"rollForward": false
},
"microsoft.openapi.kiota": {
"version": "1.22.3",
"version": "1.23.0",
"commands": [
"kiota"
],
Expand Down
32 changes: 26 additions & 6 deletions docs/usage/openapi-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The following code generators are supported, though you may try others as well:

# [NSwag](#tab/nswag)

For C# clients, we provide an additional package that provides workarounds for bugs in NSwag and enables using partial PATCH/POST requests.
For C# clients, we provide an additional package that provides workarounds for bugs in NSwag and enables using partial POST/PATCH requests.

To add it to your project, run the following command:
```
Expand Down Expand Up @@ -146,16 +146,36 @@ From here, continue from step 3 in the list of steps for Visual Studio.

# [Kiota](#tab/kiota)

To generate your C# client, install the Kiota tool by following the steps at https://learn.microsoft.com/en-us/openapi/kiota/install#install-as-net-tool.

Next, generate client code by running the [command line tool](https://learn.microsoft.com/en-us/openapi/kiota/using#client-generation). For example:
To generate your C# client, first add the Kiota tool to your solution:

```
dotnet kiota generate --language CSharp --class-name ExampleApiClient --output ./GeneratedCode --backing-store --exclude-backward-compatible --clean-output --clear-cache --openapi http://localhost:14140/swagger/v1/swagger.json
dotnet tool install microsoft.openapi.kiota
```

After adding the `JsonApiDotNetCore.OpenApi.Client.Kiota` package to your project, add a `KiotaReference` element
to your project file to import your OpenAPI file. For example:

```xml
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<KiotaReference Include="path/to/openapi.json">
<NamespaceName>$(MSBuildProjectName).GeneratedCode</NamespaceName>
<ClassName>ExampleApiClient</ClassName>
<OutputPath>./GeneratedCode</OutputPath>
<ExtraArguments>$(JsonApiExtraArguments)</ExtraArguments>
</KiotaReference>
</ItemGroup>
</Project>
```

> [!NOTE]
> The `ExtraArguments` parameter is required for compatibility with JSON:API.
Next, build your project. It runs the kiota command-line tool, which generates files in the `GeneratedCode` subdirectory.

> [!CAUTION]
> The `--backing-store` switch is needed for JSON:API partial PATCH/POST requests to work correctly.
> If you're not using `<KiotaReference>`, at least make sure you're passing the `--backing-store` switch to the command-line tool,
> which is needed for JSON:API partial POST/PATCH requests to work correctly.
Kiota is pretty young and therefore still rough around the edges. At the time of writing, there are various bugs, for which we have workarounds
in place. For a full example, see the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/openapi/src/Examples/OpenApiKiotaClientExample).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
<!-- Loosely based on https://github.com/kimbell/Kiota.Testing, related to https://github.com/microsoft/kiota/issues/3005 -->
<Project>
<UsingTask TaskName="KiotaPatchGeneratedCodeFiles" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<StartDirectory ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Class" Language="cs">
<![CDATA[
using System;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public sealed class KiotaPatchGeneratedCodeFiles : Task
{
private static readonly Regex HeaderRegex = new(@"// <auto-generated/>(?:\r\n|\n|\r)(#pragma|using)", RegexOptions.Singleline | RegexOptions.Compiled);
private static readonly Regex NullableRegex = new(@"(?s)#if NETSTANDARD2_1_OR_GREATER .*?(?:\r\n|\n|\r)#nullable enable(?:\r\n|\n|\r)(?<ifBody>.*?)(?:\r\n|\n|\r)#nullable restore(?:\r\n|\n|\r)#else(?:\r\n|\n|\r)(?<elseBody>.*?)(?:\r\n|\n|\r)#endif", RegexOptions.Singleline | RegexOptions.Compiled);
private static readonly Regex LineBreaksRegex = new(@"}(?:\r\n|\n|\r)(?<lineIndent>[ ]+/// <summary>)", RegexOptions.Singleline | RegexOptions.Compiled);
public string StartDirectory { get; set; }
public override bool Execute()
{
string absoluteStartDirectory = Path.GetFullPath(StartDirectory);
Log.LogMessage(MessageImportance.High, $"Patching kiota output files in {absoluteStartDirectory}");
foreach (string path in Directory.GetFiles(absoluteStartDirectory, "*.cs", SearchOption.AllDirectories))
{
string content = File.ReadAllText(path);
content = HeaderRegex.Replace(content, $"// <auto-generated/>{Environment.NewLine}#nullable enable{Environment.NewLine}#pragma warning disable CS8625{Environment.NewLine}$1");
content = NullableRegex.Replace(content, "$1");
content = LineBreaksRegex.Replace(content, $"}}{Environment.NewLine}{Environment.NewLine}$1");
File.WriteAllText(path, content);
Log.LogMessage(MessageImportance.Normal, $"Patched file: {path}");
}
return true;
}
}
]]>
</Code>
</Task>
</UsingTask>

<!-- Restore local tools -->
<Target Name="_KiotaRestoreTools" Condition="'$(KiotaAutoRestoreTools)' == 'true'">
Expand Down Expand Up @@ -140,11 +184,6 @@
<Exec Command="$(_KiotaCommand) %(KiotaReference.Arguments)" EnvironmentVariables="KIOTA_TUTORIAL_ENABLED=false;KIOTA_OFFLINE_ENABLED=true" />

<!-- Post-process output files -->
<Message Importance="High" Condition="'$(KiotaPatchOutput)' == 'true'" Text="Patching kiota output files in %(KiotaReference.OutputPath)" />
<Exec Condition="'$(KiotaPatchOutput)' == 'true'" ConsoleToMSBuild="true"
Command="pwsh $(MSBuildThisFileDirectory)kiota-patch-generated-code.ps1 %(KiotaReference.OutputPath)">
<Output TaskParameter="ConsoleOutput" ItemName="OutputLinesOfScript" />
</Exec>
<Error Condition="'@(OutputLinesOfScript)' != ''" Text="@(OutputLinesOfScript, '%0a')" />
<KiotaPatchGeneratedCodeFiles StartDirectory="%(KiotaReference.OutputPath)" />
</Target>
</Project>

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
<None Include="..\..\PackageReadme.md" Visible="false" Pack="True" PackagePath="" />
<None Include="Build\*.props" Pack="True" PackagePath="build" />
<None Include="Build\*.targets" Pack="True" PackagePath="build" />
<None Include="Build\*.ps1" Pack="True" PackagePath="build" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 3356544

Please sign in to comment.