Odrai
Odrai

Reputation: 2353

Build errors after creating an openapi client via Connected Services

I would like to add an OpenAPI service reference to an existing project. Within the Connected Services view, the next values are used:

enter image description here

Afterwards I click on Finish, build the project and add the PetStoreApiClient.cs to the project.

Finally I try to build the solution (again) while using the PetStoreApiClient. Visual Studio displays several compile errors, e.g.:

enter image description here

Several items are duplicated, even the baseUrl is generated multiple times:

Ambiguity between 'PetStoreApiClient.BaseUrl' and 'PetStoreApiClient.BaseUrl'   ConsoleApp  C:\..\ConsoleApp\ConsoleApp\obj\openapi1Client.cs

The csproj file contains the next settings, as visualized in the first screenshot:

 <ItemGroup>
<OpenApiReference Include="OpenAPIs\openapi.json" CodeGenerator="NSwagCSharp" ClassName="PetStoreApiClient" OutputPath="PetStoreApiClient.cs">
  <SourceUri>https://petstore3.swagger.io/api/v3/openapi.json</SourceUri>
</OpenApiReference>

Should I use different settings? Add a setting within the csproj? A similar issue is described on GitHub, but the provided solutions don't work.

Upvotes: 5

Views: 2251

Answers (2)

Odrai
Odrai

Reputation: 2353

I ended up using NSwag.MSBuild, works flawlessly!

The result is a TestClient.cs and TestClient.Interface.cs. The TestClient can be used to execute the requests.

nswag.json

{
  "runtime": "NetCore31",
  "defaultVariables": "Configuration=Debug",
  "documentGenerator": {
    "fromDocument": {
      "url": "<your url>/swagger.json"
    }
  },
  "codeGenerators": {
    "openApiToCSharpClient": {
      "generateClientInterfaces": true,
      "exceptionClass": "$(SdkName)ApiException",
      "useBaseUrl": true,
      "generateBaseUrlProperty": true,
      "generateContractsOutput": true,
      "contractsNamespace": "$(SdkNamespace).Interface",
      "contractsOutputFilePath": "Generated\\$(GeneratedContractFile)",
      "className": "$(SdkName)",
      "operationGenerationMode": "SingleClientFromOperationId",
      "namespace": "$(SdkNamespace)",
      "output": "Generated\\$(GeneratedClientFile)"
    }
  }
}

csproj

<Target Name="GenerateSdk" BeforeTargets="Build">
    <PropertyGroup>

        <NSwagConfiguration>nswag.json</NSwagConfiguration>
        <SdkNamespace>$(RootNamespace)</SdkNamespace>
        <SdkName>TestClient</SdkName>
        <GeneratedInterfaceFile>$(SdkName).Interface.cs</GeneratedInterfaceFile>
        <GeneratedServiceFile>$(SdkName).cs</GeneratedServiceFile>

    </PropertyGroup>
    <Error Text="The NSwag configuration '$(NSwagConfiguration)' does not exists!" Condition="!Exists('$(NSwagConfiguration)')" />
    <Exec Command="$(NSwagExe_Core31) run $(NSwagConfiguration) /variables:Configuration=$(Configuration),SdkName=$(SdkName),SdkNamespace=$(SdkNamespace),GeneratedClientFile=$(GeneratedServiceFile),GeneratedContractFile=$(GeneratedInterfaceFile)" />
</Target>

Upvotes: 3

Robin
Robin

Reputation: 51

I had the same issue and a very hard time finding a good answer.

Until I found this: https://github.com/RicoSuter/NSwag/issues/334

“If you have multiple controllers, you have to either choose OperationGenerationMode.SingleClientFromOperationId or use the placeholder {controller} in your controller class name.”

So my issue was solved by simply providing “{controller}Client” as class name.

Upvotes: 5

Related Questions