Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I use NSwag.ApiDescription.Client? #2251

Open
Eneuman opened this issue Jun 18, 2019 · 14 comments
Open

Can I use NSwag.ApiDescription.Client? #2251

Eneuman opened this issue Jun 18, 2019 · 14 comments

Comments

@Eneuman
Copy link

Eneuman commented Jun 18, 2019

Hi!
I'm trying to use the NSwag.ApiDescription.Client to generate a C# client using "ServiceProjectReference" (as described here https://github.com/RicoSuter/NSwag/wiki/ServiceProjectReference) but I'm getting a

Microsoft.Extensions.ApiDescription.Client.targets(141,5): error : ServiceProjectReference items are no longer supported.

exception :(

I know this is still under development but I would like to beta test it :)
Is it posible to use this with .Net Core 2.2 atm or is it outdated?

@RicoSuter
Copy link
Owner

/cc @dougbu

@dougbu
Copy link
Contributor

dougbu commented Jun 18, 2019

The latest NSwag.ApiDescription.Client includes a reference to the latest Microsoft.ApiDescription.Client package but, because #2226 is not merged, doesn't support project references. Either

@Eneuman
Copy link
Author

Eneuman commented Jun 19, 2019

Thank you for your quick reply. We have decided to go back to using the .Design version while waiting for a “preview” version :). Do you know if the ApiDescription.Client will be .net Core 3.0 only or will it work for 2.2 as well?

@dougbu
Copy link
Contributor

dougbu commented Jun 19, 2019

Do you know if the ApiDescription.Client will be .net Core 3.0 only or will it work for 2.2 as well?

If you mean the Microsoft.Extensions.ApiDescription.Client package, it should work for most target frameworks because it contains only MSBuild files. For future reference, the Microsoft.Extensions.ApiDescription.Server package for document generation in web projects supports .NET Framework 4.6.1 and .NET Core 2.1 or later.

The NSwag.ApiDescription.Client package supports .NET Framework 4.6.1 and .NET Core 1.0 or later.

@dougbu
Copy link
Contributor

dougbu commented Jun 19, 2019

Switch to @(OpenApiReference) items, referencing OpenAPI .json files you download manually from your web project

I re-tested this locally and found there's a bug in the NSwag.ApiDescription.Client -- it references an older version of NSwag.MSBuild but uses the latest NSwag CLI commands. You could resolve this by directly referencing the same version of NSwag.MSBuild from your project. But, you might want to wait for a release containing the #2226 updates. (I fixed the dependency from NSWag.ApiDescription.Client.nuspec in that PR because it was inconsistent, not realizing the change addressed a real bug.)

@Eneuman
Copy link
Author

Eneuman commented Jul 31, 2019

@RicoSuter Do you know if #2226 was included in the latest 13.0.4 release?

We are using the old preview functionality in 12.x atm but we can switch once this works to try it out and give feedback if you want :)

@RicoSuter
Copy link
Owner

@Eneuman

Do you know if #2226 was included in the latest 13.0.4 release?

Yes it is available in the latest version.

@Eneuman
Copy link
Author

Eneuman commented Sep 23, 2019

I'm trying to get the Client generation going with the new .Net Core 3.0 bits but I just can't seem to figure it out.

Should I be using NSwag.ApiDescription.Client or the Microsoft.Extensions.ApiDescription.Server package to generate a C# client at build?

Using "Microsoft.Extensions.ApiDescription.Server" gives me an error telling me if cannot find the start point.
Using "NSwag.ApiDescription.Client" gives me an error telling me "ServiceProjectReference items are no longer supported."

@dougbu
Copy link
Contributor

dougbu commented Sep 23, 2019

NSwag.ApiDescription.Client is the correct package to reference. But, it currently brings in an old version of the Microsoft.Extensions.ApiDescription.Client package. To update it, also add a reference to the 3.0.0 version of Microsoft.Extensions.ApiDescription.Client however you prefer to update package references. The end result should be something like

    <PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="3.0.0">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>

The items you want to include in your project for code generation are now named @(OpenApiReference), not @(ServiceProjectReference) or any of the old names.

@Eneuman
Copy link
Author

Eneuman commented Sep 24, 2019

Thanks for the info!

I can see that the OpenApiReference now wants me to reference a .json file directly and not a .csproj file as the old one did.

I can create a .json file from my Micro Service project using the msbuild task, but I dont want to pay the compilation time cost every time I rebuild that project. Are there another way to create the .json file only when I rebuild my "Client" project?

@dougbu
Copy link
Contributor

dougbu commented Sep 24, 2019

@(OpenApiProjectReference) items are somewhat supported for project-to-project references. That feature is experimental at this point due to some rough edges in the API project you're referencing.

Set <OpenApiGenerateDocumentsOnBuild >false</OpenApiGenerateDocumentsOnBuild > in the API project to disable writing documents to disk on every build. Then, invoke the GenerateOpenApiDocuments explicitly whenever you do want to write the documents.

@Eneuman
Copy link
Author

Eneuman commented Sep 27, 2019

I dont mind rough edges :)
I got it some what working using the following values in my client project file.

  <ItemGroup>
    <OpenApiProjectReference Include="../Organisation.Personal.Service/Organisation.Personal.Service.csproj">
      <CodeGenerator>NSwagCSharp</CodeGenerator>
      <ClassName>PersonalClient</ClassName>
      <Options>/UseBaseUrl:false /GenerateClientInterfaces:true</Options>
    </OpenApiProjectReference>
  </ItemGroup>

Everything is almost as I want it except three issues:

  1. Adding a <OutputPath>..</OutputPath> causes NSwag to fail with a access error. Creating the client in the root of the project was working with NSwag 12.x. @RicoSuter
1>NSwag bin directory: C:\Users\XXXXXXX\.nuget\packages\nswag.msbuild\13.1.0\tools\Win
1>System.Reflection.TargetInvocationException: Ett undantagsfel har inträffat i målet för en aktivering. ---> System.UnauthorizedAccessException: Access to path C:\Repos\Organisation_Personal_Service\src\Organisation.Personal.Client denied.
1>   vid System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
1>   vid System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
1>   vid System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
1>   vid System.IO.StreamWriter.CreateFile(String path, Boolean append, Boolean checkHost)
1>   vid System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize, Boolean checkHost)
1>   vid System.IO.File.InternalWriteAllText(String path, String contents, Encoding encoding, Boolean checkHost)
1>   --- Slut på stackspårning för interna undantag ---
1>   vid System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
1>   vid System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
1>   vid System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
1>   vid NJsonSchema.Infrastructure.DynamicApis.FileWriteAllText(String filePath, String text)
1>   vid NSwag.Commands.OutputCommandExtensions.<TryWriteFileOutputAsync>d__2.MoveNext()
1>--- Slut på stackspårningen från föregående plats där ett undantag utlöstes ---
1>   vid System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
1>   vid NSwag.Commands.CodeGeneration.SwaggerToCSharpClientCommand.<RunAsync>d__82.MoveNext()
1>--- Slut på stackspårningen från föregående plats där ett undantag utlöstes ---
1>   vid System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
1>   vid System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
1>   vid NConsole.CommandLineProcessor.<ProcessSingleAsync>d__12.MoveNext()
1>--- Slut på stackspårningen från föregående plats där ett undantag utlöstes ---
1>   vid System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
1>   vid NConsole.CommandLineProcessor.<ProcessAsync>d__11.MoveNext()
1>--- Slut på stackspårningen från föregående plats där ett undantag utlöstes ---
1>   vid System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
1>   vid System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
1>   vid NConsole.CommandLineProcessor.Process(String[] args, Object input)
1>   vid NSwag.Commands.NSwagCommandProcessor.Process(String[] args)
1>C:\Users\PerBornsjö\.nuget\packages\nswag.apidescription.client\13.1.0\build\NSwag.ApiDescription.Client.targets(28,5): error MSB3073: The command ""C:\Users\PerBornsjö\.nuget\packages\nswag.msbuild\13.1.0\build\../tools/Win/NSwag.exe" openapi2csclient /className:PersonalClient /namespace:eClinic.Organisation.Personal.Client /input:C:\Repos\Organisation_Personal_Service\src\Organisation.Personal.Service\obj\Organisation.Personal.Service.json /output:obj\.. /UseBaseUrl:false /GenerateClientInterfaces:true" exited with code -1.
1>Done building project "Organisation.Personal.Client.csproj" -- FAILED.

Both the obj and the root path has the same security settings.

  1. For this to work I need to always create the .json file whenever I build my API Project. If I disable the creation (setting it to false in api .csproj) my CI build will fail since my API Project throws an error saying that this setting needs to be enabled. Manually editing the .csproj every time we work on a service is not fun. This is a blocker for us.

  2. Using OpenApiProjectReference triggers Visual Studio to take a dependency on that project. This must be a bug since it's only using command tools to run it and have no visual code dependencies.
    I want my client to be .Net Standard 2.0 and my API to run .Net Core 3.0, but this does not seem to be working.

What I realy would want is to:

  1. From the API project, tell my Service project to build a .json and add it to my API project root folder. I want the .json file to be source controlled so I can use version controll to check what has changed.
  2. After the .json file have been created in the API client project, I want a Client (.cs file) to be created and added to the root folder. I want this file to be source controlled aswell.

Adding both theese files to source control makes it easy to check whenever a update to NSwag or other package, changes the behavior of the client.

Is this solution possible with todays version of OpenApiProjectReference?

@dougbu
Copy link
Contributor

dougbu commented Sep 28, 2019

  1. <OutputPath>..</OutputPath> needs to include a filename, not just a relative folder
  2. What exactly do you mean by "Manually editing the .csproj every time we work on a service is not fun."? Or, what happens when you've got <OpenApiGenerateDocumentsOnBuild>false</OpenApiGenerateDocumentsOnBuild> in an API project and an @(OpenApiProjectReference) item to the API project in another project?
  3. Please also clarify "Using OpenApiProjectReference triggers Visual Studio to take a dependency on that project." What version of Visual Studio? Are you talking about how things display in the VS solution explorer or something else?
    • FYI an @(OpenApiProjectReference) item actually is a @(ProjectReference) item. This ensures the two projects are built in the correct order.

BTW I tend to use "API project" when referring to an ASP.NET Core MVC project exposing a Web API and "client project" when referring to the project containing (generated) code to use that API. What do you mean by "API project" and "service project"?

@vancodocton
Copy link

  <PropertyGroup>
    <OpenApiCodeDirectory>$(ProjectDir)</OpenApiCodeDirectory>
  </PropertyGroup>
  
  <ItemGroup>
    <OpenApiProjectReference Include="..\WebApi\WebApi.csproj">
      <CodeGenerator>NSwagCSharp</CodeGenerator>
      <Options>/GenerateClientInterfaces:true /UseBaseUrl:false</Options>
    </OpenApiProjectReference>
  </ItemGroup>

It maybe helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants