RicoSuter/NSwag

The wiki/documentation you have on various things are out of date and were not update since 2019

vamsidogiparthi opened this issue · 8 comments

Hi,
Your documentation is very outdated and not easy to understand as well. Example below wiki document is completely outofdate as we are no longer using webApiToDocument for .NET 6 or plus. Nor assembly paths etc. We have to search many sites and forums to even understand what we have to do as part of 14.08 to make it work. As .NET or microsoft is recommending NSwag for everyone. You should be vigilant enough to update your wiki as well as provide clear instructions for every use case.

Also, you nswag new creates a json document with NetCore21 framework and not document generation setting. Which is another suggestion from our side.

https://github.com/RicoSuter/NSwag/wiki/NSwag-Configuration-Document

Just spent a couple of hours trying to solve issues with generated default values and nullability. To find the "generateOptionalPropertiesAsNullable" property, which solved the issues for me, i had to download NSwag studio, save a dummy config and find the property in the saved .nswag file, because the documentation is out of date.

I agree. Coming from swashbuckle I am still unable to find out how Nswag works regarding generation of open API JSON out of the app (preferably .net8+). Is there any working sample, somewhere, where I could see how to extract open API Json during CI/CD pipeline without having to run the app?

@diegosasw , @ahl-trifork I have been writing some medium articles on this very topic. See if those help you out in anyway. All of them are attached with a working github repos. so, might give you some heads up. If you need any further help. Let me know and I will be adding some complex use cases soon to my medium.

@diegosasw in your scenario my article related to MSbuild will help you with u r use case

https://medium.com/@vamsidogiparthi/learn-and-understand-how-to-generate-swagger-json-via-msbuild-and-net-8-with-simple-start-up-d7ad6c3cf74b

@vamsidogiparthi thank you. Your article helped and for a simple web project it works well.
I tried to bring that knowledge to my existing project, after successfully creating a sample like yours and I am finding many issues.

When running dotnet nswag run nswag.json it behaves as if it was ignoring that my launchSettings.json has a "ASPNETCORE_ENVIRONMENT": "Development" because it tries to run certain things that shouldn´t as per a custom flag in my appsettings.Development.json

Also, it seems that when running dotnet nswag run nswag.json I cannot read env variables in my Program.cs with Environment.GetEnvironmentVariable("Foo") to control the flow.

As I understand, NSwag runs the application in order to generate the openapi.json document, so I should have some control over the program flow when running the app from nswag, right?

This is my nswag.json

{
  "runtime": "Net80",
  "defaultVariables": null,
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
      "project": "MyWebApi.csproj",
      "defaultUrlTemplate": "api/{controller}/{id?}",
      "configuration": null,
      "noBuild": true,
      "verbose": true,
      "requireParametersWithoutDefault": false,
      "apiGroupNames": null,
      "defaultPropertyNameHandling": "Default",
      "defaultReferenceTypeNullHandling": "Null",
      "defaultDictionaryValueReferenceTypeNullHandling": "NotNull",
      "defaultResponseReferenceTypeNullHandling": "NotNull",
      "generateOriginalParameterNames": true,
      "defaultEnumHandling": "String",
      "flattenInheritanceHierarchy": false,
      "generateKnownTypes": true,
      "generateEnumMappingDescription": false,
      "generateXmlObjects": false,
      "generateAbstractProperties": false,
      "generateAbstractSchemas": true,
      "ignoreObsoleteProperties": false,
      "allowReferencesWithProperties": false,
      "useXmlDocumentation": true,
      "resolveExternalXmlDocumentation": true,
      "excludedTypeNames": [],
      "serviceSchemes": [],
      "infoTitle": "WebApiOne Project",
      "infoDescription": "OpenAPI Specification for WebApiOne",
      "infoVersion": "1.0.0",
      "documentProcessorTypes": [],
      "operationProcessorTypes": [],
      "useDocumentProvider": true,
      "documentName": "v1",
      "aspNetCoreEnvironment": null,
      "createWebHostBuilderMethod": null,
      "startupType": null,
      "allowNullableBodyParameters": true,
      "useHttpAttributeNameAsOperationId": false,
      "output": ".openapi/openapi.json",
      "outputType": "OpenApi3",
      "newLineBehavior": "Auto",
      "assemblyPaths": [],
      "referencePaths": [],
      "useNuGetCache": false
    }
  }
}

If I specify "aspNetCoreEnvironment": "Development" then it throws some exception like

Application terminated unexpectedly due to Could not load file or assembly 'NSwag.CodeGeneration, Version=14.1.0.0, Culture=neutral, PublicKeyToken=c2d88086e098d109'. The system cannot find the file specified.
System.IO.FileNotFoundException: Could not load file or assembly 'NSwag.CodeGeneration, Version=14.1.0.0, Culture=neutral, PublicKeyToken=c2d88086e098d109'. The system cannot find the file specified.

If I explicitly add that nuget package as dependency, it does not make any difference.

I couldn't find anything in documentation to help me understand what's going on. I don't know if .NET 8 is supported or not, and why reading from settings or env variables becomes a problem, or why the configuration of aspNetCoreEnvironment does not work as expected.

@diegosasw sorry for the late reply. I have done similar environment specific changes to my project program.cs/startup.cs. To further continue our conversation. Can you answer my below questions?

  1. Do you have your repository, somewhere on the github or online repo which i can take a look at?
  2. Are you trying to generate a swagger open api json file during post build process or during your pipeline run? If so, don't use this comman dotnet nswag run nswag.json Please look at the repository i have shared in the article to see how to add it to the MSBuild post deployment process as i did the same for my pipeline code to look at a specific path after the msbuild has been completed. I can help you with it as well.
  3. In terms of reading environment variables. Are you using .Net 8 with only program.cs file or do you have separate program.cs and startup.cs? if your program.cs is the only file then you can get the environment name with the below code to only configure certain things if the environment is not 'nswag' etc.if (builder.Environment.IsEnvironment("NSwag") { }
  4. you need to use the below command in the msbuild for your purpose also update you nswag.json to include few variables.
	<Target Name="NSwag" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
		<!-- A good practice to restore the project nuget packages to make sure the next step doesn't fail. -->
		<Exec Command="dotnet tool restore"></Exec>
		<!-- An exec command to generate swagger.json file as part of the build process.
		EnvironmentVariables = allows you to set the project environment variable
		WorkingDirectory = holds the directory path from which the command has to be executed
		Command = holds the command to be executed when this exec block is executed during post build process
		. -->
		<Exec WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=NSwag" Command="$(NSwagExe_Net80) run nswag.json /variables:Configuration=$(Configuration),Environment=NSwag" />
	</Target>

{
"runtime": "Net80",
"defaultVariables": "Configuration=Debug,Environment=Development"
"documentGenerator": {
"aspNetCoreToOpenApi": {
"configuration": "$(Configuration)", // configuration for the project such as Debug, Release etc.
"aspNetCoreEnvironment": "$(Environment)", // environment for the asp.net core application
}
}

@vamsidogiparthi thanks for the information. I finally got something working.

Do you have your repository, somewhere on the github or online repo which i can take a look at?

Yes. I've created this minimum example.
https://github.com/diegosasw/sample-open-api-nswag/tree/1f1420a5e87a1a8e82681ffa8abc72da9f433a1c

Are you trying to generate a swagger open api json file during post build process or during your pipeline run?

I am trying both ways. I like the MSBuild RunPostBuildEvent mechanism but, in theory, it also works with running the dotnet nswag run nswag.json from command line. Both are now working well for me.

In terms of reading environment variables. Are you using .Net 8 with only program.cs file or do you have separate program.cs and startup.cs?

Just Program.cs in .NET 8. The thing I was stuck with is knowing how to discriminate between Program launching when running the app, and the launching when running NSwag. Your configuration helped me configure that in nswag.json, thanks.

Now I can ensure NSwag execution sets the environment NSwag and allows me to discriminate. This was the tricky part.

// The goal is to skip certain things when running NSwag
// View the nswag.json to see how NSwag is set as environment
var isNSwagExecution = builder.Environment.IsEnvironment("NSwag");
if (!isNSwagExecution)
{
    throw new Exception("Sample exception to demonstrate that NSwag should skip this");
}

This didn't work in my nswag.json

{
  "runtime": "Net80",
  "defaultVariables": null,
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
           //....
           "aspNetCoreEnvironment": "NSwag",
    }
  }
}

This didn't work either

{
  "runtime": "Net80",
  "defaultVariables": "Configuration=Debug,Environment=NSwag",
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
           //....
           "aspNetCoreEnvironment": null,
    }
  }
}

But this works well

{
  "runtime": "Net80",
  "defaultVariables": "Configuration=Debug,Environment=NSwag",
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
           //....
           "aspNetCoreEnvironment": "$(Environment)",
    }
  }
}

Your help is much appreciated. I wouldn't have figured this out by simply reading the documentation!

Unfortunately, when I try to apply the same approach to an existing project which I can't share, I am getting the following errors when nswag dotnet tool runs (both when building solution or when running through command line)

[15:29:50 INF] Starting application
[15:29:50 FTL] Application terminated unexpectedly due to Could not load file or assembly 'NSwag.CodeGeneration, Version=14.1.0.0, Culture=neutral, PublicKeyToken=c2d88086e098d109'. The system cannot find the file specified.
System.IO.FileNotFoundException: Could not load file or assembly 'NSwag.CodeGeneration, Version=14.1.0.0, Culture=neutral, PublicKeyToken=c2d88086e098d109'. The system cannot find the file specified.
File name: 'NSwag.CodeGeneration, Version=14.1.0.0, Culture=neutral, PublicKeyToken=c2d88086e098d109'
2>MyProject.Api.csproj(62,9): Error MSB3073 : The command "dotnet "C:\NuGet\nswag.msbuild\14.1.0\buildTransitive\../tools/Net80/dotnet-nswag.dll" run nswag.json" exited with code -1.
2>------- Finished building project: MyProject.Api Succeeded: False. Errors: 1. Warnings: 0
Build completed in 00:00:02.171

Probably there are some things I need to exclude also, or probably when there are more assemblies in the equation I need to add some additional dependencies in an explicit way...
I am using Fastendpoints in my "real" project. I'll have to check if there's something there that doesn't work nicely with NSwag.

@diegosasw sorry i got busier with other office and personal work. Where you able to figure out the issue? I am thinking its not able to find the project file or nswag.json file. Make sure the file is under the executing assemby project directory. If you need anymore help ping me. I will try to be more active on git hub. if you have discord let me know your handle i can connect help out there as well.