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

NSwag v14 preview announcement & breaking changes #4524

Open
RicoSuter opened this issue Sep 26, 2023 · 99 comments
Open

NSwag v14 preview announcement & breaking changes #4524

RicoSuter opened this issue Sep 26, 2023 · 99 comments

Comments

@RicoSuter
Copy link
Owner

RicoSuter commented Sep 26, 2023

Please test the preview packages for NSwag v14 and NJsonSchema v11 and report problems here.

Note: NSwag/NJS still uses Newtonsoft.Json for serializing/deserializing schemas internally, so for now it still requires newtonsoft as a reference, internal serialization will hopefully migrated to STJ in the next major version.

This whole major version is about dropping old stuff to make the project maintainable again. I'm testing it with my more or less modern ASP.NET Core applications. The goal is that the tooling still works with them and there are no regressions or very hard to mitigate breaking changes.

NSwag v14

PR: #3758

Breaking changes

  • NJsonSchema generator settings moved from being directly on the generator settings to the "SchemaSettings" property.
  • nswag.json now only supports .csproj based specification generation (reflection/assembly based removed, only aspnetcore2openapi)
  • Now only supports .NET Standard 2.0, .NET 4.6.2, .NET Core 3.1, .NET 5, .NET 7 and up
  • Requires latest Newtonsoft.Json v13.0.0.3
  • Removed many deprecated properties, settings and methods (marked a long time as obsolete)
  • Removed WebApiToOpenApiCommand: Use the WebApiOpenApiDocumentGenerator to build your own CLI referencing controllers project to generate OpenAPI without starting the app
  • Renamed UseSwaggerUi3 to UseSwaggerUi (v2 has been removed)

NJsonSchema v11

PR: RicoSuter/NJsonSchema#1450 (merged)

Breaking changes

  • All Newtonsoft.Json based generators moved to NJsonSchema.NewtonsoftJson
  • Requires latest Newtonsoft.Json v13.0.0.3
  • Now only supports .NET Standard 2.0, .NET 4.6.2 and up
  • Updated to latest Namotion.Reflection v3
  • Breaking change in IJsonExtensionObject interface (now supports multiple data tuples)

Other changes:

  • Add support for STJ-native inheritance schema generation (JsonDerivedType, JsonPolymorphic)
  • Many more smaller improvements and fixes (see git history)
@RicoSuter RicoSuter pinned this issue Sep 26, 2023
@Numpsy
Copy link
Contributor

Numpsy commented Sep 27, 2023

Hi,

The 14.0.0-preview004 package for NSwag.ApiDescription.Client seems to have a dependency of

NSwag.MSBuild (>= 14.0.0)

and when I try to update in Visual Studio it complains because NSwag.MSBuild only has 14.0.0-preview00N packages

@RicoSuter
Copy link
Owner Author

@Numpsy try v14.0.0-preview005

@Numpsy
Copy link
Contributor

Numpsy commented Sep 27, 2023

Ok, the new version has installed ok

@RicoSuter RicoSuter changed the title NSwag v14 (preview) announcement & breaking changes NSwag v14 preview announcement & breaking changes Sep 28, 2023
@olegd-superoffice
Copy link
Contributor

Both .NET Core 3.1 and .NET 5 are out of support already and .NET 8 is around the corner. So maybe drop support for old versions?

@lahma
Copy link
Collaborator

lahma commented Sep 28, 2023

@olegd-superoffice there's #4001 for that

@Numpsy
Copy link
Contributor

Numpsy commented Sep 28, 2023

fwiw I've dropped the v14 test packages into a project that contains an asp .net core 3.1 web service and a mix of client builds using different .net versions, but one of the reasons for that is that I'm trying to see what's going on with the Mend complaints described at #2824 - and as long as I can generate client code that can build as .NET Standard 2.0 it doesn't matter if the code generator itself needs .NET 6+ and I don't have any pressing need to update the server side itself

@lahma
Copy link
Collaborator

lahma commented Oct 1, 2023

  • nswag.json now only supports .csproj based specification generation (reflection/assembly based removed, only aspnetcore2openapi)

I wonder if this now makes it impossible to generate API specification and clients via MSBuild. Seems that now MSBuild will invoke NSwag's run target (with nswag.json etc) like documented in MSBuild integration guidance which in turn now needs to gather the project metadata by invoking MSBuild against the csproj (DLL no longer supported), which in turn will again invoke the nswag run and the recursion will continue...

There's also quite a lot of performance penalty from invoking the build pipeline multiple times.

EDIT, so the way nswag.json needs to be configured is to have "noBuild": true in it when invoked from csproj.

@RicoSuter
Copy link
Owner Author

EDIT, so the way nswag.json needs to be configured is to have "noBuild": true in it when invoked from csproj.

Exactly, if you run this as part of the csproj build (after build) then you need to enable noBuild

@Tomius
Copy link

Tomius commented Oct 4, 2023

nswag.json now only supports .csproj based specification generation (reflection/assembly based removed, only aspnetcore2openapi)

Nit: the docs will eventually need to be updated to reflect this, e.g. WebApiToOpenApiCommand

Out of curiosity, what was the reason to remove this feature?

I mean, I understand that having fewer commands makes the code easier to maintain. But it feels very sad to have start up the application to generate swagger from it, when it's used at large scale. E.g. the build and prod enviornments might be very different and the app might not start up on the build machine. Or it might do some very expensive intialisation, like read from databases, that might significantly increase build times (if the nswag generation happens during the build).

I am aware that I could put all the controllers into a library and have two Asp.Net core apps, one for prod doing the real initialisation, and a "dummy one" just for nswag. But having to do this just feels so painful compared to how easy it was to use NSwag v13.

@RicoSuter
Copy link
Owner Author

RicoSuter commented Oct 4, 2023

Out of curiosity, what was the reason to remove this feature?

Main reason is that all this legacy stuff puts a lot of maintenance effort.
The main pain is this whole dynamic assembly loading stuff.
I cannot maintain legacy frameworks, .net runtimes forever alone without even being paid for it...

The web api generator is still available, so the simplest solution for you would be to just build your own simple CLI tool which uses the
https://github.com/RicoSuter/NSwag/wiki/WebApiOpenApiDocumentGenerator
and references the project with the controllers...

I am aware that I could put all the controllers into a library and have two Asp.Net core apps

Did you use WebApiToOpenApiCommand for ASP.NET Core? That's a very bad idea as it uses reflection and not the API explorer which might lead to completely wrong results...

@m-demydiuk
Copy link

m-demydiuk commented Oct 24, 2023

Version 14.0.0-preview008 has a reference to Microsoft.Extensions.ApiDescription.Server v6.0.3.
Is it correct?
image

@RicoSuter
Copy link
Owner Author

Is this a problem?

@m-demydiuk
Copy link

@RicoSuter we have all other packages (also transitive) in our project updated to the latest version, except this. Is there any blocker not to update this one to latest?

@olegd-superoffice
Copy link
Contributor

@m-demydiuk This reference is only setting minimal supported version of the package, but you always can use newer ones in your project if you reference the dependency directly of if you use NuGet's central package management with CentralPackageTransitivePinningEnabled.
But there are many use cases where it is not possible to use the latest version and keeping this reference to minimal supported version allows it to be used in those cases.

@Herdo
Copy link

Herdo commented Nov 4, 2023

@RicoSuter Will there also be a preview of the NSwagStudio 14.x ? 😄

@lahma
Copy link
Collaborator

lahma commented Nov 4, 2023

@Herdo the studio setup MSI should now be part of the release assets.

@Gigas002
Copy link

What's about OpenAPI v3.1.0/swagger-ui v5? This is being constantly asked since 2021 in a #3761, but haven't been answered still. Are these a planned features, at least?

@vipwan
Copy link

vipwan commented Nov 15, 2023

In v14 preview AspNetCoreOpenApiDocumentGeneratorSettings removed the SchemaProcessors property , how should I register a custom ISchemaProcessor

@chriscameron-vertexinc
Copy link

It looks like JsonSchemaGeneratorSettings is gone, removing the UseXmlDocumentation option on AddSwaggerDocument. Should we not be using XML documentation to drive the Swagger documentation anymore?

@lahma
Copy link
Collaborator

lahma commented Nov 15, 2023

@vipwan @chriscameron-vertexinc

services.AddSwaggerDocument(document =>
{
    document.SchemaSettings.SchemaProcessors.Add(null!);
    document.SchemaSettings.UseXmlDocumentation = true;
});

@chriscameron-vertexinc
Copy link

chriscameron-vertexinc commented Nov 15, 2023

nswag.json
Here's an odd one. I'm using a post build step to run NSwagExe_Net80:

  <Target Name="NSwag" AfterTargets="Build">
    <Exec Command="$(NSwagExe_Net80) run nswag.json /variables:Configuration=$(Configuration)" />
  </Target>

My nswag.json aspNetCoreToOpenApi document generator has the following assembly path:

      "assemblyPaths": [
        "bin/$(Configuration)/net8.0/CNR.Example.API.dll"
      ],

Since following the advice above to set noBuild to true this is working perfectly in VS2022 when I build for Debug or Release.

In my CI/CD pipeline I'm doing the following:

dotnet restore ./src/CNR.Example.API.sln
dotnet build ./src/CNR.Example.API.sln --maxcpucount --configuration Release --no-restore

This also works perfectly from my local command line, however on my build machine I get:

  NSwag command line tool for .NET Core Net80, toolchain v14.0.0.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))
  Visit http://NSwag.org for more information.
  NSwag bin directory: /root/.nuget/packages/nswag.msbuild/14.0.0-preview009/tools/Net80
  
  Executing file 'nswag.json' with variables 'Configuration=Release'...
  System.InvalidOperationException: Project outputs could not be located in '/home/ubuntu/actions-runner/_work/cnr-example-api/cnr-example-api/src/CNR.Example.API/bin/Debug/net8.0/'. Ensure that the project has been built.
     at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 82
     at NSwag.Commands.NSwagDocumentBase.GenerateSwaggerDocumentAsync() in /_/src/NSwag.Commands/NSwagDocumentBase.cs:line 270
     at NSwag.Commands.NSwagDocument.ExecuteAsync() in /_/src/NSwag.Commands/NSwagDocument.cs:line 67
     at NSwag.Commands.Document.ExecuteDocumentCommand.ExecuteDocumentAsync(IConsoleHost host, String filePath) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 76
     at NSwag.Commands.Document.ExecuteDocumentCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 33
     at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
     at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
     at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 62
/home/ubuntu/actions-runner/_work/cnr-example-api/cnr-example-api/src/CNR.Example.API/CNR.Example.API.csproj(54,5): error MSB3073: The command "dotnet "/root/.nuget/packages/nswag.msbuild/14.0.0-preview009/buildTransitive/../tools/Net80/dotnet-nswag.dll" run nswag.json /variables:Configuration=Release" exited with code 255.

It looks like NSwagExe_Net80 isn't replacing the $(Configuration) value in my nswag.json properly. It clearly says Executing file 'nswag.json' with variables 'Configuration=Release' and then complains that it can't find the file in the Debug directory.

The exact same script, and exact same machine, when working with .net7.0:

  NSwag command line tool for .NET Core Net70, toolchain v13.20.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))
  Visit http://NSwag.org for more information.
  NSwag bin directory: /root/.nuget/packages/nswag.msbuild/13.20.0/tools/Net70
  
  Executing file 'nswag.json' with variables 'Configuration=Release'...
  Done.
  
  Duration: 00:00:01.3889592

@RicoSuter
Copy link
Owner Author

@chriscameron-vertexinc assembly path loading has been removed, use “project” with path to csproj instead

@RicoSuter
Copy link
Owner Author

JsonSchemaGeneratorSettings Is part of NJsonSchema and now a property and not inheritance anymore.. mainly because there are now two variants: system.text.json and newtonsoft..

@chriscameron-vertexinc
Copy link

@chriscameron-vertexinc assembly path loading has been removed, use “project” with path to csproj instead

I've now updated my nswag.json to use project instead of assemblyPaths and I'm seeing the exact same problem.

It looks like I misspoke when I said I couldn't reproduce the problem locally. After deleting my bin directories to clear out the Debug output my post build step is failing in VS2022 release builds.

image

@yfital
Copy link

yfital commented Nov 16, 2023

Sorry, i would really appreivcate a clarification on how we are supposed to work here with the removal of the WebApi2Swagger.
We have 2 use cases:

  1. We have an internal SDK which includes our hosting capabilities and various controllers
    1.2. These are dlls, not .exes which do not contain startup
    1.3. All our of programs inherit these
    1.4 Our UI uses a document create from the SDK for all general purpose controllers and specific code from documents from the console applications

  2. We have a multi dll console application, where the controllers sit in the DLLs and not in the console

Our current solution was simple, in the SDK, we used WebApi2Swagger to create the openapi

In our DLLs

(Notice, in the DLL we also exported the document for the SDK counterpart)
  • Our actual .exe doesn't have any reference to nswag.msbuild, it doesn't need it
  • Our .exe(s) are heavy one, i prefer to create the openapi it without having to run it

am i missing something here? are we working completly wrong?

@lahma
Copy link
Collaborator

lahma commented Nov 16, 2023

@chriscameron-vertexinc

We had to tune the configuration a bit after enabling <UseArtifactsOutput>true</UseArtifactsOutput> (docs) . Maybe this can give some configuration clues for you, key is to point msBuildProjectExtensionsPath to obj folder and have configuration passed in as variable, our mileage may vary.

{
  "runtime": "Net70",
  "defaultVariables": null,
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
      "project": null,
      "documentName": "v1",
      "msBuildProjectExtensionsPath": "../../artifacts/obj/TheProjectFolder",
      "configuration": "$(Configuration)",

@chriscameron-vertexinc
Copy link

Thanks so much @lahma !

In summary, I've had to change the following to get NSwagExe_80 to work for me:

  • Change API csproj post build to use NSwagExe_80
  • Change nswag.json runtime to net80
  • Change nswag.json nobuild to true
  • Change nswag.json project to the path to my csproj file
  • Change nswag.json configuration to "$(Configuration)"
  • Change nswag.json assemblyPaths to []
  • Fix instances of UpdateJsonSerializerSettings in the clients to be static
  • Move UseXmlDocumentation from the document to the schema settings

@aviita
Copy link
Contributor

aviita commented Jan 8, 2024

Out of curiosity, what was the reason to remove this feature?

Main reason is that all this legacy stuff puts a lot of maintenance effort. The main pain is this whole dynamic assembly loading stuff. I cannot maintain legacy frameworks, .net runtimes forever alone without even being paid for it...

The web api generator is still available, so the simplest solution for you would be to just build your own simple CLI tool which uses the https://github.com/RicoSuter/NSwag/wiki/WebApiOpenApiDocumentGenerator and references the project with the controllers...

I am aware that I could put all the controllers into a library and have two Asp.Net core apps

Did you use WebApiToOpenApiCommand for ASP.NET Core? That's a very bad idea as it uses reflection and not the API explorer which might lead to completely wrong results...

We also relied on the now removed approach (WebApiToOpenApiCommand). So now looking for a workaround. So it is still going to be around for a while although being marked as deprecated for dotnet core?

Important: This reflection based generator is deprecated for ASP.NET Core projects and replaced by the new APi Explorer based generator AspNetCoreOpenApiDocumentGenerator!

We ran into this when upgrading to dotnet 8 and had to update nswag.

@trejjam
Copy link
Sponsor Contributor

trejjam commented Jan 8, 2024

You can get a clue what went wrong by executing dotnet "C:\Users\.nuget\packages\nswag.msbuild\14.0.0\buildTransitive\../tools/Net80/dotnet-nswag.dll" run nswag.json /variables:Configuration=Debug from command line, while being in the directory where is located your nswag.json

@raix
Copy link

raix commented Jan 14, 2024

We are currently facing inconsistent output where keys are:

  • Correctly CamelCase when swagger.json is generated via controller
  • Unexpected PascalCase when generated via the CLI command aspnetcore2openapi

This is unexpected, feels like a bug could also be a missing configuration 😅

Any hints are much appreciated 🙏


Snippet of the generated `swagger.json` via controllers:
      "CreateUserCommand": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "tenantId": {
            "$ref": "#/components/schemas/TenantId"
          },
          "email": {
            "type": "string"
          },
          "userRole": {
            "$ref": "#/components/schemas/UserRole"
          }
        }
      },
Snippet of the generated `swagger.json` via CLI tool:
      "CreateUserCommand": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "TenantId": {
            "$ref": "#/components/schemas/TenantId"
          },
          "Email": {
            "type": "string"
          },
          "UserRole": {
            "$ref": "#/components/schemas/UserRole"
          }
        }
      },

References to code:

(we are using .Net 8 Minimal Api's in PlatformPlatform and referenced code is from a WIP Pull-Request)

@trejjam
Copy link
Sponsor Contributor

trejjam commented Jan 14, 2024

Something like this should help you :)

public static class OpenApiDocumentGeneratorSettingsExtensions
{
    public static void ConfigureSchemaSettings(
        this AspNetCoreOpenApiDocumentGeneratorSettings settings, IServiceProvider serviceProvider
    )
    {
        if (settings.SchemaSettings is SystemTextJsonSchemaGeneratorSettings systemTextJsonSchemaGeneratorSettings)
        {
            var originalJsonOptions = serviceProvider.GetRequiredService<IOptions<JsonOptions>>().Value.SerializerOptions;
            var jsonOptions = new JsonSerializerOptions(originalJsonOptions);
            jsonOptions.Converters.Add(new JsonStringEnumConverter());

            systemTextJsonSchemaGeneratorSettings.SerializerOptions = jsonOptions;
        }
    }
}

IServiceCollection.AddOpenApiDocument((settings, serviceProvider) => settings.ConfigureSchemaSettings(serviceProvider));

@raix
Copy link

raix commented Jan 14, 2024

Thanks! @trejjam for the quick reply, that fixed the issue 🎉
Reference for anyone facing a similar issue Inlined version in PlatformPlatform

@MehdiElMellali
Copy link

I recently updated to NSwag v14.0.1 and noticed that the "classNames" feature in the "typesToOpenApi" configuration has been removed. I have specific models, like "MyClassDto," that I need to include in the generated TypeScript code. I am seeking guidance on how to replace the "classNames" configuration in the latest version.

{
  "typesToOpenApi": {
    "classNames": [
      "MyClassDto"
    ]
  }
}

I need to include only certain C# models in the TypeScript output. How can I achieve this with the latest version of NSwag?

@dougclutter
Copy link

Just adding a note here in case it helps someone else.

While upgrading to .NET 8 and NSwag 14, we ran into errors while building trying to use the NSwag command line tools with the aspnetcore2swagger option which has been removed. With .NET 7 and NSwag 13.20, we used this in our csproj files:

<Exec WorkingDirectory="$(TargetDir)" Command="$(NSwagExe_Net70) aspnetcore2swagger /assembly:Sample.dll /output:$(ProjectDir)swagger.json" />

With .NET 8 and NSwag 14.0.1, we had to change this to:

<Exec Command="$(NSwagExe_Net80) aspnetcore2openapi /project:Sample.csproj /output:swagger.json /nobuild:true" />

Also, in our Program.cs file, we had to change app.UseSwaggerUi3(); to app.UseSwaggerUi();; but Rico mentioned that in his post.

@valadas
Copy link

valadas commented Jan 16, 2024

I have many many projects that used reflection on .NetFramework, so I created this "wrapper" nuget package that kinda provide a similar CLI experience to generate the specs. It uses but does not replace NSwag. https://github.com/valadas/WebApiToOpenApiReflector

@denhaandrei
Copy link

After Updating to Net8 with migrate NSwag 13.20.0.0 (NJsonSchema v10.9.0.0) to v14.0.2.0 (NJsonSchema v11.0.0.0).
Api started successfully and the new JSON was updated but angular did not start with this configuration.

{
  "runtime": "Net80",
  "defaultVariables": null,
  "documentGenerator": {
    "aspNetCoreToOpenApi": {
      "project": "Test.Web.csproj",
      "msBuildProjectExtensionsPath": null,
      "configuration": null,
      "runtime": null,
      "targetFramework": null,
      "noBuild": true,
      "verbose": false,
      "workingDirectory": null,
      "requireParametersWithoutDefault": true,
      "apiGroupNames": null,
      "defaultPropertyNameHandling": "CamelCase",
      "defaultReferenceTypeNullHandling": "Null",
      "defaultDictionaryValueReferenceTypeNullHandling": "NotNull",
      "defaultResponseReferenceTypeNullHandling": "NotNull",
      "defaultEnumHandling": "Integer",
      "flattenInheritanceHierarchy": false,
      "generateKnownTypes": true,
      "generateEnumMappingDescription": false,
      "generateXmlObjects": false,
      "generateAbstractProperties": false,
      "generateAbstractSchemas": true,
      "ignoreObsoleteProperties": false,
      "allowReferencesWithProperties": false,
      "excludedTypeNames": [],
      "serviceHost": null,
      "serviceBasePath": null,
      "serviceSchemes": [],
      "infoTitle": "Test Web API",
      "infoDescription": null,
      "infoVersion": "1.0.0",
      "documentTemplate": null,
      "documentProcessorTypes": [],
      "operationProcessorTypes": [],
      "typeNameGeneratorType": null,
      "schemaNameGeneratorType": null,
      "contractResolverType": null,
      "serializerSettingsType": null,
      "useDocumentProvider": false,
      "documentName": "v1",
      "aspNetCoreEnvironment": null,
      "createWebHostBuilderMethod": null,
      "startupType": null,
      "allowNullableBodyParameters": true,
      "output": "wwwroot/api/specification.json",
      "outputType": "OpenApi3",
      "assemblyPaths": [],
      "assemblyConfig": null,
      "referencePaths": [],
      "useNuGetCache": false
    }
  },
  "codeGenerators": {
    "openApiToTypeScriptClient": {
      "className": "{controller}Client",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 5.2,
      "template": "Angular",
      "promiseType": "Promise",
      "httpClass": "HttpClient",
      "useSingletonProvider": false,
      "injectionTokenType": "InjectionToken",
      "rxJsVersion": 7.8,
      "dateTimeType": "Date",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": true,
      "generateOptionalParameters": true,
      "exportTypes": true,
      "wrapDtoExceptions": false,
      "exceptionClass": "SwaggerException",
      "clientBaseClass": null,
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "protectedMethods": [],
      "configurationClass": null,
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": false,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "markOptionalProperties": true,
      "generateCloneMethod": false,
      "typeStyle": "Class",
      "classTypes": [],
      "extendedClasses": [],
      "extensionCode": null,
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "excludedParameterNames": [],
      "handleReferences": false,
      "generateConstructorInterface": true,
      "convertConstructorInterfaceData": false,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "queryNullValue": "",
      "inlineNamedDictionaries": false,
      "inlineNamedAny": false,
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": "ClientApp/src/app/service-proxies/service-proxies.ts"
    }
  }
}

Updates in Generated service-proxies.ts using the NSwag toolchain v14.0.2.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)):
1.

this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : ""; 

changed to

this.baseUrl = baseUrl ?? "http://";
    getClientById(id: string | null): Observable<ClientModel> {
        let url_ = this.baseUrl + "/Clients/GetClientById?";
        if (id === undefined)
            throw new Error("The parameter 'id' must be defined.");
        else if(id !== null)
            url_ += "id=" + encodeURIComponent("" + id) + "&";

changed to

    getClientById(id?: string | null | undefined): Observable<ClientModel> {
        let url_ = this.baseUrl + "/Clients/GetClientById?";
        if (id !== undefined && id !== null)
            url_ += "id=" + encodeURIComponent("" + id) + "&";
export interface ClientModel{
    id?: string | undefined;
    statusId?: number;
}

changed to:

export interface ClientModel{
    id?: string | undefined;
    statusId?: number | undefined;
}

any ideas how to fix this?

@gavin-theta
Copy link

I recently updated to NSwag v14.0.1 and noticed that the "classNames" feature in the "typesToOpenApi" configuration has been removed. I have specific models, like "MyClassDto," that I need to include in the generated TypeScript code. I am seeking guidance on how to replace the "classNames" configuration in the latest version.

{
  "typesToOpenApi": {
    "classNames": [
      "MyClassDto"
    ]
  }
}

I need to include only certain C# models in the TypeScript output. How can I achieve this with the latest version of NSwag?

I'm having the same issue. Our type definitions live in model libraries rather than asp net core services directly. Good practice I believe. How do we generate types from a library build now?

@R0binSmit
Copy link

R0binSmit commented Feb 2, 2024

After I migrated to .net 8, I changed the generation of the swagger file to be project-based

	<Target Name="NSwag" AfterTargets="PostBuildEvent">
		<Exec Command="$(NSwagExe_Net80) aspnetcore2openapi /project:X.API.csproj /output:swagger.json /nobuild:true" />
		<Exec Command="$(NSwagExe_Net80) openapi2tsclient /input:swagger.json /output:../../XCTWebFE/src/app/api/X.ts /template:Angular /typeScriptVersion:4.9 /InjectionTokenType:InjectionToken /rxJsVersion:7.8 /useTransformOptionsMethod:true /clientBaseClass:ClientBase /extensionCode:import{ClientBase}from'./ClientBase';" />
	</Target>

Locally, it works wonderfully. However, the project cannot be found or assigned in the build process in the Azure DevOps pipeline. See error message:

  NSwag bin directory: C:\Users\VssAdministrator\.nuget\packages\nswag.msbuild\14.0.2\tools\Net80
  System.InvalidOperationException: Project outputs could not be located in 'D:\a\1\s\X\X\bin\Debug\net8.0-windows\'. Ensure that the project has been built.
     at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 82
     at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
     at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
     at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 62
##[error]XCTWebBE\XCTWeb.API\XCTWeb.API.csproj(42,3): Error MSB3073: The command "dotnet "C:\Users\VssAdministrator\.nuget\packages\nswag.msbuild\14.0.2\buildTransitive\../tools/Net80/dotnet-nswag.dll" aspnetcore2openapi /project:X.csproj /output:swagger.json /nobuild:true" exited with code -1.

Update 02/05/2024
I found the issue. The pipeline use the release build to generate the assembly but Nswag search in the debug folder for the build output. I have not yet found a solution to give NSwag aspnetcore2openapi the configuration. I would like to denounce the fact that the documentation and its maintenance is really poor here. I have now provisionally solved the problem by creating the debug directory and copying the assembly there if Release is built.

	<Target Name="CopyAssemblyForNswag" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release' And !Exists('$(OutputPath)\..\..\Debug\net8.0-windows')">
		<Exec Command="cd &quot;$(OutDir)&quot; &amp;&amp; mkdir &quot;..\..\Debug\net8.0-windows\&quot;" />
		<Exec Command="cd &quot;$(OutDir)&quot; &amp;&amp; xcopy &quot;.\&quot; &quot;..\..\Debug\net8.0-windows\&quot; /E " />
	</Target>

@R0binSmit
Copy link

R0binSmit commented Feb 5, 2024

@chriscameron-vertexinc assembly path loading has been removed, use “project” with path to csproj instead

I've now updated my nswag.json to use project instead of assemblyPaths and I'm seeing the exact same problem.

It looks like I misspoke when I said I couldn't reproduce the problem locally. After deleting my bin directories to clear out the Debug output my post build step is failing in VS2022 release builds.

image

I have the same issue in another context.
I have now provisionally solved the problem by creating the debug directory and copying the assembly there if Release is built.

@andreicalin246
Copy link

We had to migrate our api from .net7 to .net 8. After migration our typescript client has some issues:

export class UserDto implements IUserDto {
    id?: string;
    name?: string;
    email?: string;
    phone?: string;

    constructor(data?: IUserDto) {
        if (data) {
            for (var property in data) {
                if (data.hasOwnProperty(property))
                    (<any>this)[property] = (<any>data)[property];
            }
        }
    }

    init(_data?: any) {
        if (_data) {
            this.id = _data["Id"] !== undefined ? _data["Id"] : <any>null;
            this.name = _data["Name"] !== undefined ? _data["Name"] : <any>null;
            this.email = _data["Email"] !== undefined ? _data["Email"] : <any>null;
            this.phone = _data["Phone"] !== undefined ? _data["Phone"] : <any>null;
        }
    }

Main issue is because we have _data["Name"] instead _data["name"]. Is there a setting to make it camelCase instead PascalCase?

@lahma
Copy link
Collaborator

lahma commented Feb 13, 2024

@andreicalin246 see #4524 (comment)

@dmitry-pavlov
Copy link

In v14 preview AspNetCoreOpenApiDocumentGeneratorSettings removed the SchemaProcessors property , how should I register a custom ISchemaProcessor

Something like that @vipwan

services.AddOpenApiDocument(options =>
{
    options.SchemaSettings.SchemaProcessors.Add(new MyISchemaProcessor());
});

@IanKemp
Copy link

IanKemp commented Mar 13, 2024

Seems like the operationProcessorTypes parameter in nswag.json is now silently ignored, you have to manually add them:

        services.AddOpenApiDocument(options =>
        {
            options.OperationProcessors.Add(new MyOperationProcessor());
        });

Yet another breaking change that is not documented in any way shape or form. This is why my organisation is moving to Kiota.

@xantari
Copy link

xantari commented Mar 18, 2024

UseXmlDocumentation doesn't seem to load XML documentation for other assemblies in V14... Has anyone got this to work?

@SSRazvan
Copy link

SSRazvan commented Mar 19, 2024

Upgrade to .NET 8.0 and NSwag.AspNetCore 14.0.3 Exec NSwag exited with code -1. Has anyone any idea how to fix this?

My command:

<Target Name="NSwag" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
    <Exec ConsoleToMSBuild="true" WorkingDirectory="$(ProjectDir)" EnvironmentVariables="ASPNETCORE_ENVIRONMENT=Localhost" Command="$(NSwagExe_Net80) run /variables:Configuration=$(Configuration)">
    </Exec>
</Target>

My nswag.json
{ "runtime": "Net80", "defaultVariables": null, "documentGenerator": { "aspNetCoreToOpenApi": { "project": "WebUI.csproj", "msBuildProjectExtensionsPath": null, "configuration": null, "runtime": null, "targetFramework": null, "noBuild": true, "msBuildOutputPath": null, "verbose": false, "workingDirectory": null, "requireParametersWithoutDefault": true, "apiGroupNames": null, "defaultPropertyNameHandling": "CamelCase", "defaultReferenceTypeNullHandling": "Null", "defaultDictionaryValueReferenceTypeNullHandling": "NotNull", "defaultResponseReferenceTypeNullHandling": "NotNull", "generateOriginalParameterNames": true, "defaultEnumHandling": "Integer", "flattenInheritanceHierarchy": false, "generateKnownTypes": true, "generateEnumMappingDescription": false, "generateXmlObjects": false, "generateAbstractProperties": false, "generateAbstractSchemas": true, "ignoreObsoleteProperties": false, "allowReferencesWithProperties": false, "useXmlDocumentation": true, "resolveExternalXmlDocumentation": true, "excludedTypeNames": [], "serviceHost": null, "serviceBasePath": null, "serviceSchemes": [], "infoTitle": "Test API", "infoDescription": null, "infoVersion": "1.0.0", "documentTemplate": null, "documentProcessorTypes": [], "operationProcessorTypes": [], "typeNameGeneratorType": null, "schemaNameGeneratorType": null, "contractResolverType": null, "serializerSettingsType": null, "useDocumentProvider": true, "documentName": "v1", "aspNetCoreEnvironment": null, "createWebHostBuilderMethod": null, "startupType": null, "allowNullableBodyParameters": true, "useHttpAttributeNameAsOperationId": false, "output": "wwwroot/api/specification.json", "outputType": "OpenApi3", "newLineBehavior": "Auto", "assemblyPaths": [], "assemblyConfig": null, "referencePaths": [], "useNuGetCache": false } }, "codeGenerators": { "openApiToTypeScriptClient": { "className": "{controller}Client", "moduleName": "", "namespace": "", "typeScriptVersion": 4.3, "template": "Angular", "promiseType": "Promise", "httpClass": "HttpClient", "withCredentials": false, "useSingletonProvider": true, "injectionTokenType": "InjectionToken", "rxJsVersion": 7.0, "dateTimeType": "Date", "nullValue": "Undefined", "generateClientClasses": true, "generateClientInterfaces": true, "generateOptionalParameters": false, "exportTypes": true, "wrapDtoExceptions": false, "exceptionClass": "SwaggerException", "clientBaseClass": null, "wrapResponses": false, "wrapResponseMethods": [], "generateResponseClasses": true, "responseClass": "SwaggerResponse", "protectedMethods": [], "configurationClass": null, "useTransformOptionsMethod": false, "useTransformResultMethod": false, "generateDtoTypes": true, "operationGenerationMode": "MultipleClientsFromOperationId", "markOptionalProperties": true, "generateCloneMethod": false, "typeStyle": "Class", "enumStyle": "Enum", "useLeafType": false, "classTypes": [], "extendedClasses": [], "extensionCode": null, "generateDefaultValues": true, "excludedTypeNames": [], "excludedParameterNames": [], "handleReferences": false, "generateConstructorInterface": true, "convertConstructorInterfaceData": false, "importRequiredTypes": true, "useGetBaseUrlMethod": false, "baseUrlTokenName": "API_BASE_URL", "queryNullValue": "", "useAbortSignal": false, "inlineNamedDictionaries": false, "inlineNamedAny": false, "includeHttpContext": false, "templateDirectory": null, "typeNameGeneratorType": null, "propertyNameGeneratorType": null, "enumNameGeneratorType": null, "serviceHost": null, "serviceSchemes": null, "output": "ClientApp/src/app/web-api-client.ts", "newLineBehavior": "Auto" } } }

@SoleCode
Copy link

SoleCode commented Mar 25, 2024

I have upgraded to v14 and the build is failing. Here is configuration I have and it works with v13

<OpenApiReference Include="OpenAPIs\swagger.json" CodeGenerator="NSwagCSharp" Namespace="Portal.Api" ClassName="ApiClient">
	<OutputPath>$(ProjectDir)/OpenAPIs/ApiClient.cs</OutputPath>
	<Options>/JsonLibrary:SystemTextJson /OperationGenerationMode:SingleClientFromOperationId /InjectHttpClient:false /ClientClassAccessModifier:public /GenerateClientInterfaces:true /UseBaseUrl:false /GeneratePrepareRequestAndProcessResponseAsAsyncMethods:true /DateType:System.DateOnly /GenerateDefaultValues:false /InjectHttpClient:fasle /UseHttpClientCreationMethod:true</Options>
</OpenApiReference>

@MoeHamdan
Copy link

Hello

I used to use
"apiGroupNames": [
"v2"
],
now it is being replaced by
"documentName": "v1",

I am setting it to "documentName": "v2", however this throws the following exception System.InvalidOperationException: No registered OpenAPI/Swagger document found for the document name 'v2'. Add with the AddSwagger()/AddOpenApi() methods in ConfigureServices().

Note that "documentName": "v1", works but generates both v1 and v2, I only want to generate v2.

Thanks.

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