RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.78k stars 1.29k forks source link

Export additional models #3441

Open rhegner opened 3 years ago

rhegner commented 3 years ago

I'm using NSwag in my ASP.NET Core project (app.UseOpenApi()).

Is it possible to add additional models, which are not used in any controller action, to the generated api descriptions?

jeremyVignelles commented 3 years ago

Did you try [KnownType("AdditionalType")]?

rhegner commented 3 years ago

And where do I add this attribute? On any of my controllers?

(My current workaround is to create a dummy endpoint which uses the additional type).

RicoSuter commented 3 years ago

You can also programmatically add additional schemas in PostProcess or a document processor with the schema generator in the context object.

vladimir-djokic commented 3 years ago

Did you try [KnownType("AdditionalType")]?

Decorating class Foo with [KnownType("Foo")] does not result in exported type (when using TypeScript client generator)

RicoSuter commented 3 years ago

It's [KnownType(typeof(Foo))] on an exposed class Bar

vladimir-djokic commented 3 years ago

It's [KnownType(typeof(Foo))] on an exposed class Bar

What if Bar does not inherit Foo? How to export stand-alone type that is not referenced by any of the Web API controllers - is it possible?

RicoSuter commented 3 years ago

I think that doesnt matter, its just a way to tell the gen to include it.. its not used as inheritance.

RicoSuter commented 3 years ago

Otherwise:

You can also programmatically add additional schemas in PostProcess or a document processor with the schema generator in the context object.

vladimir-djokic commented 3 years ago

I think that doesnt matter, its just a way to tell the gen to include it.. its not used as inheritance.

I tried this:

[KnownType(typeof(Foo))]
public class Foo
{
    [JsonConstructor]
    public Foo(string name)
    {
        this.name = name;
    }

    public readonly string name;
}

And it does not produce any additional output.

Otherwise:

You can also programmatically add additional schemas in PostProcess or a document processor with the schema generator in the context object.

I don't understand what this means.

My setup



This setup results in two `.ts` files:
- `Types.ts`
- `Clients.ts`

I have custom templates for both. What would I need to change in order for `Foo` to be added as output for `Types.ts`?
lahma commented 3 years ago

Here's an example processor for those who would like to use one.

/// <summary>
///  Registers additional types that cannot be directly seen from Web API, like SignalR messages.
/// </summary>
public sealed class AddAdditionalTypeProcessor<T>: IDocumentProcessor where T : class
{
    public void Process(DocumentProcessorContext context)
    {
        context.SchemaResolver.AddSchema(typeof(T), isIntegerEnumeration: false, JsonSchema.FromType<T>());
    }
}

And usage:

services.AddSwaggerDocument(settings =>
{
    settings.DocumentProcessors.Add(new AddAdditionalTypeProcessor<MyTypeToExport>());
});
minya commented 2 years ago

How to do this for Owin WebApi?

FerdinandBrunauer commented 2 years ago

Here's an example processor for those who would like to use one.

/// <summary>
///  Registers additional types that cannot be directly seen from Web API, like SignalR messages.
/// </summary>
public sealed class AddAdditionalTypeProcessor<T>: IDocumentProcessor where T : class
{
    public void Process(DocumentProcessorContext context)
    {
        context.SchemaResolver.AddSchema(typeof(T), isIntegerEnumeration: false, JsonSchema.FromType<T>());
    }
}

And usage:

services.AddSwaggerDocument(settings =>
{
    settings.DocumentProcessors.Add(new AddAdditionalTypeProcessor<MyTypeToExport>());
});

This example does have problems with nested types. Solution was to change the implementation to the following:

public sealed class AddAdditionalTypeProcessor<T> : IDocumentProcessor where T : class
{
    public void Process(DocumentProcessorContext context)
    {
        context.SchemaGenerator.Generate(typeof(T).ToContextualType(), context.SchemaResolver);
    }
}
ozanmut commented 2 years ago

What @lahma suggested has problems

it generates yaml with non-compliant (openapi:3.0.0) parts like type: null it causes the generated code from this yaml to have wrong types (instead of actual type it uses object type instead for the properties). It also causes some classes to be duplicated by adding 2 to the classname like Customer and Customer2.

@FerdinandBrunauer s suggestion works allright.

Sethles commented 1 year ago

@FerdinandBrunauer example worked for me as a workaround for the issue I was having. When using [FromForm] my model wasn't being generated in the Swagger Schema section. I'm not sure if there is something I missed but I used the above code to just add the model/type manually. I would prefer not to though so if anyone else has a solution or could let me know what I missed, it would be much appreciated.

image