I am using abp vnext with .net 6. I try to access the swagger ui like https://{server}:{port}/{virtualPath}/swagger/index.html, because I want to use nginx with 2nd dir. My code like this:
app.UseSwagger(c =>
{
c.PreSerializeFilters.Add((swaggerDoc, httpReq) => {
swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{vPath}"
} };
});
});
app.UseAbpSwaggerUI(c =>
{
c.SwaggerEndpoint($"{vPath}/swagger/v1/swagger.json", "Demo API");
}
but it does not work.
Related
As the title suggests, i have a .net 6 web api that I'm trying to add versioning to but swagger (swashbuckle) does not seem to understand whats going on.
Program.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddApiVersioning(setup =>
{
setup.DefaultApiVersion = new ApiVersion(1, 0);
setup.AssumeDefaultVersionWhenUnspecified = true;
setup.ReportApiVersions = true;
});
ConfigureServices(builder.Services);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"v1");
c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"v2");
});
app.Run();
void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore();
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = false;
options.ApiVersionReader = new UrlSegmentApiVersionReader();
});
services.AddSwaggerGen();
}
I have annotated my controllers like so:
[ApiVersion("1.0")]
[Route("api/v1/[controller]")]
[ApiController]
public class MessageController : ControllerBase
[ApiVersion("2.0")]
[Route("api/v2/[controller]")]
[ApiController]
public class MessageController : ControllerBase
The swagger document that is generated looks like this:
And if i select v2 from the drop down, I get this:
Nuget packages and versions installed are:
Can anyone tell me where I'm going wrong.
You'll need to add the swagger documents themselves, not just the UI for them. In your AddSwaggerGen method, add something like:
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "My API" });
c.SwaggerDoc("v2", new OpenApiInfo { Version = "v2", Title = "My API" });
});
This article seems to have covered all the aspect what you are looking for.
Please have a look.
https://referbruv.com/blog/integrating-aspnet-core-api-versions-with-swagger-ui/
Besides passing the configuration here:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API - V1", Version = "v1" });
c.SwaggerDoc("v2", new OpenApiInfo { Title = "My API - V2", Version = "v2" });
});
According to the docs you have to specify the GroupName of the controller:
[ApiVersion("2.0")]
[Route("api/v2/[controller]")]
[ApiController]
[ApiExplorerSettings(GroupName = "v2")]
public class MessageController : ControllerBase
Also, the docs show ways to customize and add conventions.
I just upgraded my project from Swashbuckle 5.6.3 to 6.0.7. I have made no code changes, but now when attempting to use the Swagger page to test the API, the URL generated by Swagger is not using https even though the page is loaded through https and all the documentation I can find says that it should infer the scheme based on the URL used to load the Swagger page.
Here is the configuration code:
services.AddSwaggerGen(c => {
c.SwaggerDoc(apiSettings.Version, new OpenApiInfo { Title = apiSettings.Name, Version = apiSettings.Version });
c.CustomSchemaIds(type => type.FullName);
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "bearer",
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{ new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new List<string>() }
});
});
and:
app.UseSwagger();
app.UseSwaggerUI(c => {
c.SwaggerEndpoint($"/swagger/{apiSettings.Version}/swagger.json", $"{apiSettings.Name} {apiSettings.Version}");
});
Is there a new configuration setting to specify the scheme now?
In version 6.0.7, you can change this behavior with the MapSwagger extension method.
app.UseEndpoints(endpoints =>
{
...
endpoints.MapSwagger($"/swagger/{apiSettings.Version}/swagger.json", o =>
{
o.PreSerializeFilters.Add((swagger, httpReq) =>
{
swagger.Servers.Clear();
});
});
});
In the end, this is the final code that worked for me.
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapSwagger("/swagger/{documentName}/swagger.json", options => {
options.PreSerializeFilters.Add((swagger, httpRequest) => { });
});
});
I want to group controller operations.
At controller level added
[ApiExplorerSettings(GroupName ="Test")]
On the SwaggerGen options added
c.DocInclusionPredicate((_, api) => !string.IsNullOrWhiteSpace(api.GroupName));
c.TagActionsBy(api => api.GroupName);
This worked fine
I then introduced versioning.
On the SwaggerGen options added
var provider = services.BuildServiceProvider()
.GetRequiredService<IApiVersionDescriptionProvider>();
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerDoc(description.GroupName,
new Info()
{
Title = $"{description.ApiVersion}",
Version = description.ApiVersion.ToString(),
Description = "Developer Guide",
});
}
Now the it fails to load the definition. if I only add
c.TagActionsBy(api => api.GroupName);
Then it groups the actions via the version number.
I'm using Swashbuckle.AspNetCore 4.0.1 and .NET Core 2.1
Any ideas/help would be appreciated
Thanks
OK, so a bit more playing and I think I've resolved by adding
c.TagActionsBy(api => new[] { "Test" });
within each api version group within SwaggerGen
Thanks if anyone was looking and sorry for wasting anyone's time
I'm encountering the same problem you're having and resolved it utilizing the following ...
options.TagActionsBy(api =>
{
string tag;
if (api.ActionDescriptor is ControllerActionDescriptor descriptor)
{
var attribute = descriptor.EndpointMetadata.OfType<ApiExplorerSettingsAttribute>().FirstOrDefault();
tag = attribute?.GroupName ?? descriptor.ControllerName;
}
else
{
tag = api.GroupName;
}
var tags = new List<string>();
if (!string.IsNullOrEmpty(tag))
{
tags.Add(tag);
}
return tags;
});
This is not complete code, but it shows the gist of what you need to do. Create a list of version info builder, and then apply that in swagger config
var versionSupportResolver = new Func<ApiDescription, string, bool>((apiDescription, version) =>
{
var path = apiDescription.RelativePath.Split('/');
var pathVersion = path[1];
return string.Equals(pathVersion, version, StringComparison.OrdinalIgnoreCase);
});
var versionInfoBuilder = new Action<VersionInfoBuilder>(info => {
info.Version("v2", "My API v2");
info.Version("v1", "My API v1");
});
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
/// ...
/// ...
c.MultipleApiVersions(versionSupportResolver, versionInfoBuilder);
/// ...
/// ...
});
in my asp.net core 2.1 api I have added static files serving and Swashbuckle, but apparently can't find the generated .json
services.AddSwaggerGen(x =>
x.SwaggerDoc("Swagger", new Info { Title = "Asp.Net Core 2 Api", Description = "Swagger Core Api" }));
----
app.UseCors("AllowAll");
app.UseAuthentication();
app.UseStaticFiles();
app.UseSwagger();
app.UseSwaggerUI(x => x.SwaggerEndpoint("/swagger/swagger.json", "Core Api"));
any idea? thanks
Your swagger end-point has the wrong Url, hence the 'Not Found' Error.
Swagger documents constructed via the default way have their url in the format /swagger/<document-name>/swagger.json where is the name (first string) parameter supplied in the call to x.SwaggerDoc("Swagger", new Info {...});
In your case you supplied "Swagger", hence your endpoint url should be "/swagger/Swagger/swagger.json".
and in your ConfigureServices your call should be like
app.UseSwaggerUI(x => x.SwaggerEndpoint("/swagger/Swagger/swagger.json", "Core Api"));
After publishing the application on IIS,
I had this same problem, here is how I solved it.
In the Startup.cs file Add in the public void ConfigureServices(IServiceCollection services)... method
services.AddSwaggerGen();
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("OpenAPISpec",
new OpenApiInfo()
{
Title = "Your Title here",
Version = "1",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact()
{
Email = "youremail#gmail.com",
Name = "Jean Fritz DUVERSEAU",
Url = new Uri("https://www.rezo509.com")
}
});
var xmlCommentFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlCommentsFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentFile);
options.IncludeXmlComments(xmlCommentsFullPath);
});
and then in the public void Configure(... method
app.UseSwagger();
app.UseSwaggerUI(s =>
{
string swaggerPath = string.IsNullOrWhiteSpace(s.RoutePrefix) ? "." : "..";
s.SwaggerEndpoint($"{swaggerPath}/swagger/OpenAPISpec/swagger.json", "Demo API");
});
After that execute the project, then in the browser modify the url as follows:
http (s): //yourserver.com:[port]/swagger/index.html
if you dont add the correct url you will have HTTP ERROR 404
And after publication on the IIS server
Long story short: you must check the path prefix difference on your environments and reflect this difference in SwaggerEndpoint([different path]) option.
One of convenient ways is to automate this difference is to put this selection to #if DEBUG section
this worked for me
`
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Test API",
Version = "v1",
Description = "List of Api's.",
Contact = new OpenApiContact
{
Name = "Test site",
Email = string.Empty
},
});
});
services.AddCors();
services.AddHttpContextAccessor();
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, HttpContextAccessor>();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json", " API V1");
c.RoutePrefix = "swagger";
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
`
Try copy pasting your application link om a browser
e.g. http://localhost/testsite/swagger/v1/swagger.json
compare it with the link in the error.
Tweak the url in c.SwaggerEndpoint accordingly
I want to use localization in an ASP.NET Core applciation that uses Areas.
I have got a partial view Areas\Admin\Views\People\GetPeopleStatistics.cshtml
In this I want to use localiuation:
...
#inject IViewLocalizer Localizer
<h3>#Localizer["People Statistics"]:</h3>
...
I created a resource file for this: Resources\Admin\Views\People\GetPeopleStatistics.en.resx
I have the following configuration in Startup.cs:
services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
.AddDataAnnotationsLocalization();
services.AddAutoMapper();
services.Configure<RequestLocalizationOptions>(
opts =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en"),
new CultureInfo("de")
};
opts.DefaultRequestCulture = new RequestCulture("en");
// Formatting numbers, dates, etc.
opts.SupportedCultures = supportedCultures;
// UI strings that we have localized.
opts.SupportedUICultures = supportedCultures;
});
Unfortunatelly this does not work. The application does not display the value from the resource file.
I am using Cookies to store the culture:
[HttpPost]
public async Task SetLanguage(string culture)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
}
I also get the following error in Visual Studio:
Custom tool PublicResXFileCodeGenerator failed to produce an output for input file 'Resources\Admin\Views\People\GetPeopleStatistics.en.resx' but did not log a specific error. WebApplication D:\SVN Repositories\SRMS\trunk\PresentationLayer\WebApplication\Resources\Admin\Views\People\GetPeopleStatistics.en.resx 1
What am I doing wrong? How can I configure this?
You might want try the following: rightclick your solution and do 'clean solution'. That solved the issue for me when localization was not working and I was 100% sure everything was configured correctly.