openiddict-ui
openiddict-ui copied to clipboard
Update ApiControllerBase.cs
Add Attribute "ApiController" in order to generate Swagger documentation
[ApiController]
I think it might be usefull also to add grouping of APIby project
[ApiExplorerSettings(GroupName = "Name-Group")]
Hi Soruk
Is having the ApiController-attribute a requirement in order to generate Swagger documentation or will it enrich the generated documentation with additional information? Honestly I do not know the details here. I thought it should be already be possible with what is there at the moment.
Regarding the ApiExplorerSettings-attribute, this is already set directly on the specific endpoint-Controllers (see the below picture).

And yes, they are hardcoded strings meaning an integrator can not change it to his will. Any suggestions on this?
Hi @thomasduft, the ApiController-attribute is mandatory to generate the Swagger documentation.
When I reference your nugets for the use with Swagger (btw the included XML documentation is not complete) I do not have any endpoints exposed by your API. I had the same issue with my main executing assemble, and when I added the given attribute, the Swagger documentation was generated for given endpoint.
Hi @Soruk
This is weird?! When I use and reference my latest published nuget openiddict-ui packages and setup the Swagger related stuff within the Startup/Program.cs file then I see the endpoints and I can also browse them.

I usually develop within devcontainers on a linux based PC with VSCode. So to me the ApiController-attribute doesn't seem to be mandatory.
Hi @thomasduft
Yes it is weird. Can you share your Startup/Program.cs, please ?
Et voilà...
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerUI;
using tomware.Suite.Host.Web;
using tomware.Suite.Persistence.EF;
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var builder = WebApplication.CreateBuilder(args);
// Add services to the container => ConfigureServices
builder.Services.Configure<StorageContextOptions>(options =>
{
options.DbContextOptionsBuilder = builder =>
builder.UseSqlite(configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(typeof(Program)
.GetTypeInfo()
.Assembly
.GetName()
.Name));
});
builder.Services.AddModules();
if (builder.Environment.IsDevelopment())
{
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "App", Version = "v1" });
c.DocInclusionPredicate((name, api) => true);
c.TagActionsBy(api =>
{
if (api.GroupName != null)
{
return new[] { api.GroupName };
}
var controllerActionDescriptor = api.ActionDescriptor as ControllerActionDescriptor;
if (controllerActionDescriptor != null)
{
return new[] { controllerActionDescriptor.ControllerName };
}
throw new InvalidOperationException("Unable to determine tag for endpoint.");
});
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
}
// Configure
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseCors(builder =>
{
builder.WithOrigins("http://localhost:4200");
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.AllowCredentials();
});
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "App v1");
c.DocExpansion(DocExpansion.None);
});
}
app.UseWebAppWithDefaults();
app.Run();
It is part of private stuff and already on .NET 6. But you should see the swagger configuration section....
Thanks.
I will check it tomorrow
Ok, I have just tested your code, and still I get only the main / executing assembly api endpoints. I do not know why I cannot to get to show the api exposed by referenced assemblies.
Same as well if you clone this repo and start the sample server? I can run it on a Linux based PC and a Windows based PC and always see the Swagger generated docs!
I have just re-downloaded the code from main branch and I can see the other assemblies documentation. When I was using the code downloaded just after release of 1.3 version, the swagger didn't work. But it works, strange... I will be investigating and keep you posted.
Hi @thomasduft, I think that I found the source of the problem. When I use
services.AddVersionedApiExplorer();
for versioning API, and the Controller does not have the given attribute [ApiController], the Swagger documentation is not generated.
I will check this solution from StackOverflow
I will check this solution from StackOverflow
And it seems that UseApiBehavior = false is the solution.
After more investigation, when I want to filer by version the methods in the following Swagger configration:
options.DocInclusionPredicate((version, desc) =>
{
if (string.IsNullOrWhiteSpace(desc.GroupName))
return false;
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
return false;
var versions = methodInfo.DeclaringType
.GetCustomAttributes(true)
.OfType<ApiVersionAttribute>()
.SelectMany(attr => attr.Versions);
var maps = methodInfo
.GetCustomAttributes(true)
.OfType<MapToApiVersionAttribute>()
.SelectMany(attr => attr.Versions)
.ToArray();
return versions.Any(v => $"v{v}" == version)
&& (!maps.Any() || maps.Any(v => $"v{v}" == version));
});
without the [ApiVersion], the filter return false.
A little tweak, fix it:
options.DocInclusionPredicate((version, desc) =>
{
if (string.IsNullOrWhiteSpace(desc.GroupName))
return false;
if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
return false;
var versions = methodInfo.DeclaringType
.GetCustomAttributes(true)
.OfType<ApiVersionAttribute>()
.SelectMany(attr => attr.Versions);
var maps = methodInfo
.GetCustomAttributes(true)
.OfType<MapToApiVersionAttribute>()
.SelectMany(attr => attr.Versions)
.ToArray();
return !versions.Any() // without version attribute
||
( versions.Any(v => $"v{v}" == version)
&& (!maps.Any() || maps.Any(v => $"v{v}" == version))
);
});