Skip to content

Commit 3356544

Browse files
authored
Kiota: Replace PowerShell script with inline MSBuild task for improved performance (#1696)
* Kiota: Replace PowerShell script with inline MSBuild task for improved performance * Update kiota and docs
1 parent 749e588 commit 3356544

File tree

5 files changed

+72
-57
lines changed

5 files changed

+72
-57
lines changed

.config/dotnet-tools.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"rollForward": false
3232
},
3333
"microsoft.openapi.kiota": {
34-
"version": "1.22.3",
34+
"version": "1.23.0",
3535
"commands": [
3636
"kiota"
3737
],

docs/usage/openapi-client.md

+26-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The following code generators are supported, though you may try others as well:
1212

1313
# [NSwag](#tab/nswag)
1414

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

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

147147
# [Kiota](#tab/kiota)
148148

149-
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.
150-
151-
Next, generate client code by running the [command line tool](https://learn.microsoft.com/en-us/openapi/kiota/using#client-generation). For example:
149+
To generate your C# client, first add the Kiota tool to your solution:
152150

153151
```
154-
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
152+
dotnet tool install microsoft.openapi.kiota
153+
```
154+
155+
After adding the `JsonApiDotNetCore.OpenApi.Client.Kiota` package to your project, add a `KiotaReference` element
156+
to your project file to import your OpenAPI file. For example:
157+
158+
```xml
159+
<Project Sdk="Microsoft.NET.Sdk">
160+
<ItemGroup>
161+
<KiotaReference Include="path/to/openapi.json">
162+
<NamespaceName>$(MSBuildProjectName).GeneratedCode</NamespaceName>
163+
<ClassName>ExampleApiClient</ClassName>
164+
<OutputPath>./GeneratedCode</OutputPath>
165+
<ExtraArguments>$(JsonApiExtraArguments)</ExtraArguments>
166+
</KiotaReference>
167+
</ItemGroup>
168+
</Project>
155169
```
156170

171+
> [!NOTE]
172+
> The `ExtraArguments` parameter is required for compatibility with JSON:API.
173+
174+
Next, build your project. It runs the kiota command-line tool, which generates files in the `GeneratedCode` subdirectory.
175+
157176
> [!CAUTION]
158-
> The `--backing-store` switch is needed for JSON:API partial PATCH/POST requests to work correctly.
177+
> If you're not using `<KiotaReference>`, at least make sure you're passing the `--backing-store` switch to the command-line tool,
178+
> which is needed for JSON:API partial POST/PATCH requests to work correctly.
159179
160180
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
161181
in place. For a full example, see the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/openapi/src/Examples/OpenApiKiotaClientExample).

src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets

+45-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
11
<!-- Loosely based on https://github.com/kimbell/Kiota.Testing, related to https://github.com/microsoft/kiota/issues/3005 -->
22
<Project>
3+
<UsingTask TaskName="KiotaPatchGeneratedCodeFiles" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
4+
<ParameterGroup>
5+
<StartDirectory ParameterType="System.String" Required="true" />
6+
</ParameterGroup>
7+
<Task>
8+
<Code Type="Class" Language="cs">
9+
<![CDATA[
10+
using System;
11+
using System.IO;
12+
using System.Text.RegularExpressions;
13+
using Microsoft.Build.Framework;
14+
using Microsoft.Build.Utilities;
15+
16+
public sealed class KiotaPatchGeneratedCodeFiles : Task
17+
{
18+
private static readonly Regex HeaderRegex = new(@"// <auto-generated/>(?:\r\n|\n|\r)(#pragma|using)", RegexOptions.Singleline | RegexOptions.Compiled);
19+
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);
20+
private static readonly Regex LineBreaksRegex = new(@"}(?:\r\n|\n|\r)(?<lineIndent>[ ]+/// <summary>)", RegexOptions.Singleline | RegexOptions.Compiled);
21+
22+
public string StartDirectory { get; set; }
23+
24+
public override bool Execute()
25+
{
26+
string absoluteStartDirectory = Path.GetFullPath(StartDirectory);
27+
Log.LogMessage(MessageImportance.High, $"Patching kiota output files in {absoluteStartDirectory}");
28+
29+
foreach (string path in Directory.GetFiles(absoluteStartDirectory, "*.cs", SearchOption.AllDirectories))
30+
{
31+
string content = File.ReadAllText(path);
32+
content = HeaderRegex.Replace(content, $"// <auto-generated/>{Environment.NewLine}#nullable enable{Environment.NewLine}#pragma warning disable CS8625{Environment.NewLine}$1");
33+
content = NullableRegex.Replace(content, "$1");
34+
content = LineBreaksRegex.Replace(content, $"}}{Environment.NewLine}{Environment.NewLine}$1");
35+
36+
File.WriteAllText(path, content);
37+
Log.LogMessage(MessageImportance.Normal, $"Patched file: {path}");
38+
}
39+
40+
return true;
41+
}
42+
}
43+
]]>
44+
</Code>
45+
</Task>
46+
</UsingTask>
347

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

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

src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/kiota-patch-generated-code.ps1

-43
This file was deleted.

src/JsonApiDotNetCore.OpenApi.Client.Kiota/JsonApiDotNetCore.OpenApi.Client.Kiota.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
<None Include="..\..\PackageReadme.md" Visible="false" Pack="True" PackagePath="" />
3030
<None Include="Build\*.props" Pack="True" PackagePath="build" />
3131
<None Include="Build\*.targets" Pack="True" PackagePath="build" />
32-
<None Include="Build\*.ps1" Pack="True" PackagePath="build" />
3332
</ItemGroup>
3433

3534
<ItemGroup>

0 commit comments

Comments
 (0)