23

I got (more than) two Api POST endpoints. Each one needs a json as parameter. But when I use the same class name Payload in two endpoint argument classes, Swagger does not work. When I change one of it e.g. from Payload to Payload1 than it works. Of course I set the right namespaces into the wrapper classes so it finds it Payload. But I would love to use the same name "Payload" each time. How can I use the same class name Payload? I can keep the json name "Payload" at both cases and just set different names for the property ("Payload1", "Payload2"). It works. But would be nice to have same property names too.,

enter image description here

Endpoint A

[HttpPost()]

public async Task PostPerson([FromBody]JsonWrapperA jsonWrapperA)

namespace myProject.A
{
    public class JsonWrapperA
    {
        [JsonProperty("name", Required = Required.AllowNull)]
        public string Name { get; set; }

        [JsonProperty("payload", Required = Required.AllowNull)]
        public Payload Payload { get; set; }
    }

    public class Payload
    {
        [JsonProperty("value", Required = Required.AllowNull)]
        public double Value { get; set; }
    }
}

Endpoint B

[HttpPost()]

public async Task PostCompagn([FromBody]JsonWrapperB jsonWrapperB)

namespace myProject.B
{
    public class JsonWrapperB
    {
        [JsonProperty("compagny", Required = Required.AllowNull)]
        public string Compagny { get; set; }

        [JsonProperty("payload", Required = Required.AllowNull)]
        public Payload Payload { get; set; }
    }

    public class Payload
    {
        [JsonProperty("age", Required = Required.AllowNull)]
        public double Age{ get; set; }
    }
}
Frank Mehlhop
  • 1,480
  • 4
  • 25
  • 48
  • 1
    Does this answer your question? [swagger error: Conflicting schemaIds: Duplicate schemaIds detected for types A and B](https://stackoverflow.com/questions/46071513/swagger-error-conflicting-schemaids-duplicate-schemaids-detected-for-types-a-a) – Michael Freidgeim Aug 31 '20 at 06:11

2 Answers2

54

By default swagger will attempt to build its Schema Ids for objects that are return types or parameter types for your APIs endpoints, and it will display these objects in the "Models" section of the documentation. It will build these schema Ids based on the class names of the objects.

When you try to have two or more classes named the same, even though they are in different namespaces, then you will get the conflicting schemaIds error:

InvalidOperationException: Conflicting schemaIds: Identical schemaIds detected for types NamespaceOne.MyClass and NamespaceTwo.MyClass. See config settings - "CustomSchemaIds" for a workaround

This means Swagger needs to be configured to change the way it generates its SchemaIds. You can simply tell swagger to use an objects fully qualified name which will include namespaces in the schemaIds. You can do this in your Startup.cs file in the ConfigureServices method like this:

//add using statement for Swagger in Startup.cs
using Swashbuckle.AspNetCore.Swagger;

...

public void ConfigureServices(IServiceCollection services)
{
    services.AddSwaggerGen(config =>
    {
        //some swagger configuration code.

        //use fully qualified object names
        config.CustomSchemaIds(x => x.FullName);
    }
}
Russell Jonakin
  • 1,716
  • 17
  • 18
  • 1
    how do we do the same thing in spring boot java ? – Sourav Mukherjee Jan 05 '20 at 10:38
  • @SouravMukherjee I am not that familiar with the Spring Boot framework, but the principal would be the same I believe. You will have to find out how to hook into the start up events of Spring, and then figure out how to configure the Swagger version you are using. This question was specific to the ASP.NET swagger wrapper called Swashbuckle, so it will be different than what is available for Spring. Here is a [swagger wrapper for Spring called SpringFox](http://springfox.github.io/springfox/docs/current/) that may help. I would recommend opening a specific swagger question for java Spring Boot. – Russell Jonakin Jan 07 '20 at 00:54
10

Using Swashbuckle.AspNetCore Version 5.5.1 i've had the same issue so i solved it using JustSomeDude answer, but afterwards all entities were shown with the full name so i needed a way to show only the name. This is what i did:

    options.CustomSchemaIds(x => x.FullName); // Enables to support different classes with the same name using the full name with namespace
    options.SchemaFilter<NamespaceSchemaFilter>(); // Makes the namespaces hidden for the schemas

Using this filter class:

     public class NamespaceSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema is null)
        {
            throw new System.ArgumentNullException(nameof(schema));
        }

        if (context is null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        schema.Title = context.Type.Name; // To replace the full name with namespace with the class name only
    }
}