'InvalidOperationException: Can't use schemaId .. The same schemaId is already used for type

I receive the following error.

InvalidOperationException: Can't use schemaId "$Registration" for type "$PortalService.Models.Registration". The same schemaId is already used for type "$PortalService.Models.Registration"

I have tried the suggestions in the following link without any succcess.

swagger error: Conflicting schemaIds: Duplicate schemaIds detected for types A and B

I only have one Registration class in models. I have tried renaming the class without success.

I am using an OData .Net Core 3.1 project.

Configure Swagger is below

 services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
            services.AddSwaggerGen(c =>
            {
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n 
                      Enter 'Bearer' [space] and then your token in the text input below.
                      \r\n\r\nExample: 'Bearer 12345abcdef'",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer"
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement()
                  {
                    {
                      new OpenApiSecurityScheme
                      {
                        Reference = new OpenApiReference
                          {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                          },
                          Scheme = "oauth2",
                          Name = "Bearer",
                          In = ParameterLocation.Header,

                        },
                        new List<string>()
                      }
                    });
            });

Use Swagger is below

  app.UseSwagger(c =>
            {
                //c.PreSerializeFilters.Add((swaggerDoc, httpReq) => swaggerDoc.BasePath = basepath);

                 
                c.PreSerializeFilters.Add((swaggerDoc, httpReq) => {
                    Microsoft.OpenApi.Models.OpenApiPaths paths = new Microsoft.OpenApi.Models.OpenApiPaths();
                    foreach (var path in swaggerDoc.Paths)
                    {
                        paths.Add(path.Key.Replace(path.Key, basepath + path.Key), path.Value);
                    }
                    swaggerDoc.Paths = paths;
                });
            });
            app.UseSwaggerUI(
                options =>
                {
                    options.RoutePrefix = string.Empty;

                    // build a swagger endpoint for each discovered API version

                    foreach (var description in provider.ApiVersionDescriptions)
                    {
                        options.SwaggerEndpoint($"{basepath}/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
                    }

                });

This appears to be related to

Swagger crashes with circular model references

I have found that if I comment out the partner back reference from registration, the error goes away but I need this reference. I am not clear how to fix the situation.

[ForeignKey("Partner")]
[DataMember(Name = "PartnerOID")]
[Column(TypeName = "VARCHAR(100)")]
public string PartnerOID { get; set; }
//public virtual Partner Partner { get; set; }


Solution 1:[1]

Try this John: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1607#issuecomment-607170559 helped me.

I can understand what is happening; i have several enums with 'Status' or 'Type'. Using options.CustomSchemaIds( type => type.ToString() ); solved this.

Solution 2:[2]

The only change needed is in your Startup.cs inside the method ConfigureServices.

You should add the following:

services.AddSwaggerGen(options =>
{
    options.CustomSchemaIds(type => type.ToString());
});

Solution 3:[3]

Here is a slightly more flexible solution

options.CustomSchemaIds(type => SwashbuckleSchemaHelper.GetSchemaId(type));

Helper

public static class SwashbuckleSchemaHelper
{
    private static readonly string _rootNamespace;
    private static readonly string _dtoFolder = "Dtos";

    static SwashbuckleSchemaHelper()
    {
        _rootNamespace = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().ManifestModule.Name);
    }

    private static string GetRelativeNamespace(string typeNamespace)
    {
        if (!typeNamespace.StartsWith(_rootNamespace))
        {
            return typeNamespace;
        }

        var relativenamespace = typeNamespace.Substring(_rootNamespace.Length + _dtoFolder.Length + 1).TrimStart('.');
        if (string.IsNullOrEmpty(relativenamespace))
        {
            return string.Empty;
        }

        return $"{relativenamespace}.";
    }

    public static string GetSchemaId(Type type)
    {
        var schemaBase = $"{GetRelativeNamespace(type.Namespace)}{type.Name}";

        if (type.IsGenericType)
        {
            string? schemaGeneric;
            if (type.GenericTypeArguments.Length > 0)
            {
                var firstItem = type.GenericTypeArguments.First();
                schemaGeneric = $"<{GetRelativeNamespace(firstItem.Namespace)}{firstItem.Name}>";
            }
            else
            {
                schemaGeneric = $"<{Guid.NewGuid()}>";
            }

            return $"{schemaBase}{schemaGeneric}";
        }

        return $"{schemaBase}";
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Erik
Solution 2
Solution 3 live2