'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 |