This issue is somewhat related to an older issue of version 2.0.0:
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/604
I have a domain xx.xx.com and a dynamic subdomain /something rewritten to / in my reverse proxy.
I've configured the UI to use a relative path with:
c.SwaggerEndpoint("v1/swagger.json", "MY API V1");
The problem is the methods are called in the root of the domain instead of with a relative path and I get error 404 for all "Try it out"s.
It calls xx.xx.com/method instead of xx.xx.com/something/method.
Any thoughts on that?
Yes, got the same error too.
I have a reverse proxy and relative path does not works correctly
Same here. Also why does "{documentName}" work for UseSwagger's RouteTemplate property but not for SwaggerEndpoint? It would seem I need to hard code the version in the endpoint URL.
Got the same issue. Anyone got a fix?
I have the application running two levels deep and it seems to be working ok (domain/subapp1/myapi/). Here are the changes I made:
app.UseSwagger(s => {
s.RouteTemplate = "docs/{documentName}/docs.json";
});
app.UseSwaggerUI(u =>
{
u.SwaggerEndpoint("../docs/v1/docs.json", "Relative API Documentation");
u.RoutePrefix = "docs";
});
My URL domain/subapp1/myapi/docs resolves nicely to the index.html and that picks up the json directives just fine.
Hope that helps!
I disagree that relative SwaggerEndpoint paths does not work, this is correct way to use it:
c#
public static class Extensions
{
public static void UseSwaggerRoute(
this IApplicationBuilder app,
IApiVersionDescriptionProvider provider,
string clientId = null,
string clientSecret = null)
{
app.UseSwagger();
app.UseSwaggerUI(__options =>
{
foreach (var versionDescription in provider.ApiVersionDescriptions)
{
__options.SwaggerEndpoint($"../{__options.RoutePrefix}/{versionDescription.GroupName}/swagger.json", versionDescription.GroupName.ToUpperInvariant());
}
if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(clientSecret))
{
__options.OAuthClientId(clientId);
__options.OAuthClientSecret(clientSecret);
}
});
}
}
I have the application running two levels deep and it seems to be working ok (domain/subapp1/myapi/). Here are the changes I made:
app.UseSwagger(s => {
s.RouteTemplate = "docs/{documentName}/docs.json";
});app.UseSwaggerUI(u =>
{
u.SwaggerEndpoint("../docs/v1/docs.json", "Relative API Documentation");
u.RoutePrefix = "docs";
});My URL domain/subapp1/myapi/docs resolves nicely to the index.html and that picks up the json directives just fine.
Hope that helps!
Agreed, relative paths "../" works both for IIS and Kestrel
Is there no "dynamic" way to modify the endpoint with a filter or something taking the base path from the request? So we need to hardcode the prefix or configure the prefix in configuration though a request would hold req.PathBase?
A dynamic way would allow to avoid any additional configuration for local development, deployments with or without sub paths.
The way to define the endpoint as "./swagger...." does not work too for me (for some reason).
As suggested by Microsoft
As a workaround I solved it with a stringcat to an endpoint prefix (prefxEndPoint):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
string prefxEndPoint = "/something";
string swaggerJsonCompl = "/v1/swagger.json";
if (env.IsDevelopment())
{
prefxEndPoint = "";
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseSwagger(c =>
{
c.RouteTemplate = "{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint(prefxEndPoint + swaggerJsonCompl, "MyApi V1");
});
app.UseMvc();
}
I think this is far from an ideal solution. Swagger should get the native attributes from ASP.NET Core Framework (baseUrl or Map).
I have two environments I have to code for and relative url is currently turning up as a blank response.
in one environment the swagger endpoint is two deep.
in another it is found at the root of the website.
`for (int version = ApplicationInfrastructure.API_CURRENT_VERSION; version <= ApplicationInfrastructure.API_CURRENT_VERSION; version++)
{
var FrameworkVersion = SwaggerUtility.GetGroupName
config.SwaggerEndpoint($"{FrameworkVersion}/swagger.json", $"IT Framework Configuration Service v{version}.0");
}`
the easiest solution is to just use the url as is in the anchor tag on the index.html page.
but the workaround that has worked in both environments was adding "./" to the beginning of the url.
I think just addin @staticdev 's solution to the documentation would be able to close this issue?
It would have saved a couple hours troubleshooting this after trying to deploy to IIS.
I disagree that relative SwaggerEndpoint paths does not work, this is correct way to use it:
public static class Extensions { public static void UseSwaggerRoute( this IApplicationBuilder app, IApiVersionDescriptionProvider provider, string clientId = null, string clientSecret = null) { app.UseSwagger(); app.UseSwaggerUI(__options => { foreach (var versionDescription in provider.ApiVersionDescriptions) { __options.SwaggerEndpoint($"../{__options.RoutePrefix}/{versionDescription.GroupName}/swagger.json", versionDescription.GroupName.ToUpperInvariant()); } if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(clientSecret)) { __options.OAuthClientId(clientId); __options.OAuthClientSecret(clientSecret); } }); } }
So what happens if you don't specify a RoutePrefix won't your endpoint be ..//?
Consolidated into #1953
Most helpful comment
I disagree that relative SwaggerEndpoint paths does not work, this is correct way to use it:
c# public static class Extensions { public static void UseSwaggerRoute( this IApplicationBuilder app, IApiVersionDescriptionProvider provider, string clientId = null, string clientSecret = null) { app.UseSwagger(); app.UseSwaggerUI(__options => { foreach (var versionDescription in provider.ApiVersionDescriptions) { __options.SwaggerEndpoint($"../{__options.RoutePrefix}/{versionDescription.GroupName}/swagger.json", versionDescription.GroupName.ToUpperInvariant()); } if (!string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(clientSecret)) { __options.OAuthClientId(clientId); __options.OAuthClientSecret(clientSecret); } }); } }