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
Related
I'm trying to implement an authorization code flow using Identity Server 4 but when I attempt to generate my authorization code all I get is a generic error page with nothing but the message 'Sorry, there was an error'. (Title is 'Error').
I get this whether I'm using Postman or programmatically submitting a GET request with the required parameters.
To run my test, in Visual studio I start the Identity server and my API server. I start my MVC site to log in as the test user if needed and to make the callback url available. I then press the 'Get New Access Token' button in Postman. The result is that generic error.
I understand that when I programmatically submit the GET request the response should be the Auth Code which would be ideal but at this point I just want to successfully authenticate the client.
Can anyone see anything I might be missing?
In Postman my parameters are as follows in this image:
My Client is set up as follows:
new Client
{
ClientId = "mvc",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code ,
// where to redirect to after login
RedirectUris = { "https://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1",
IdentityServerConstants.StandardScopes.Email
}
}
My test user is this one that comes with the Identity Server Github code:
new TestUser
{
SubjectId = "88421113",
Username = "bob",
Password = "bob",
Claims =
{
new Claim(JwtClaimTypes.Name, "Bob Smith"),
new Claim(JwtClaimTypes.GivenName, "Bob"),
new Claim(JwtClaimTypes.FamilyName, "Smith"),
new Claim(JwtClaimTypes.Email, "BobSmith#email.com"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
}
}
My Startup for Identity Server:
public class Startup
{
public IWebHostEnvironment Environment { get; }
public Startup(IWebHostEnvironment environment)
{
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
// uncomment, if you want to add an MVC-based UI
services.AddControllersWithViews();
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "<insert here>";
options.ClientSecret = "<insert here>";
});
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication (options =>
{
options.Authority = "https://localhost:5001";
options.ApiName = "testapis";
});
var builder = services.AddIdentityServer(options =>
{
// see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddDeveloperSigningCredential() //This is for dev only scenarios when you don’t have a certificate to use.
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users)
.AddCustomTokenRequestValidator<CustomTokenRequestValidator>();
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
//// uncomment if you want to add MVC
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
//// uncomment, if you want to add MVC
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
One problem is that you should always ask for the openid scope, not just ap1.
I've finally been able to get my access tokens and from what I can tell, when the AllowedGrantType on the target client is 'ClientCredentials', you cannot request the openid or profile scopes. For my test client I had added those two scopes to the AllowedScopes list but always failed to get my auth code. If I only request an ApiScope it's fine. If the scope is an IdentityResource it will not work.
This is fine as my project requires that I implement the Code grantType which I've got working to a degree.
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 am using swagger(Swashbuckle.AspNetCore 5.4.1) in asp.net Core web API project and its generating JSON with a lot of unwanted details in components as below however I was expecting it should only show useful metadata like enum details specific to my API . Please tell me if I am doing anything wrong here while setting up the swagger
Below is the code for Startup
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(su =>
{
su.SwaggerEndpoint("/swagger/general/swagger.json", "Common API");
su.RoutePrefix = string.Empty;
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
services.AddSwaggerGen(c
=>
{
c.SwaggerDoc("general", new Microsoft.OpenApi.Models.OpenApiInfo
{
Title = "Common API",
Version = "General Purpose",
Description = "TEST API",
Contact = new Microsoft.OpenApi.Models.OpenApiContact
{
Name = "VJ-TESTER",
Email = "VJ#TEST.com",
},
});
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
It may come from controllers endpoints in/out parameters.
so I have fiddled around a bit with Azure API Management Portal. I have followed the tutorial on how the import the conference api and managed to get it to work.
Then I created a WebApi app that uses swagger. My configuration is as follows:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
});
...
}
public void Configure(IApplicationBuilder app,
IServiceProvider services,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Address Service API");
});
app.UseHttpsRedirection();
app.UseMvc();
}
If I run this and navigate to https://my-api/swagger, I can see the swagger UI and I can also see the specification when I click on the link on the swagger UI or visit the url https://my-api.azurewebsites.net/swagger/v1/swagger.json
So my problem is, I have no idea on how to actually import this into AAMP. I can publish it to a app service and it works from there, but if I try to import the url https://my-api.azurewebsites.net/swagger/v1/swagger.json into the AAMP, I get an error:
So I wait an hour and try again, only the be greeted by the same error and I think I am missing something because when I imported the conference api specification, it had a different url than mine, yet I cannot find anything or I am searching for the wrong things. Can anybody please give me a heads up here?
I have also tried searching for the sources of the conference API so I can deduct what I am doing wrong but I didn't have any luck on finding those.
Importing Swagger document into APIM is pretty straight forward by following this Azure document. There’s no issue when you import Swagger 1.2 documents. However, if you’re intending to import Swagger 2.0 ones, you might be facing these kind of issue
If you’re building an API app with .NET Framework 4.5+, using Swashbuckle library, it would be fine. However, if you’re building the app with ASP.NET Core, it does bring you a headache. Firstly, look at your Startup.cs file. The ConfigureService method looks like:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen();
services.ConfigureSwaggerDocument(
options =>
{
options.SingleApiVersion(new Info() { Version = "v1", Title = "Swagger UI" });
options.IgnoreObsoleteActions = true;
options.OperationFilter(new ApplyXmlActionComments(GetXmlPath(appEnv)));
});
services.ConfigureSwaggerSchema(
options =>
{
options.DescribeAllEnumsAsStrings = true;
options.IgnoreObsoleteProperties = true;
options.CustomSchemaIds(type => type.FriendlyId(true));
options.ModelFilter(new ApplyXmlTypeComments(GetXmlPath(appEnv)));
});
...
}
private static string GetXmlPath(IApplicationEnvironment appEnv)
{
var assembly = typeof(Startup).GetTypeInfo().Assembly;
var assemblyName = assembly.GetName().Name;
var path = $#"{appEnv.ApplicationBasePath}\{assemblyName}.xml";
if (File.Exists(path))
{
return path;
}
var config = appEnv.Configuration;
var runtime = $"{appEnv.RuntimeFramework.Identifier.ToLower()}{appEnv.RuntimeFramework.Version.ToString().Replace(".", string.Empty)}";
path = $#"{appEnv.ApplicationBasePath}\..\..\artifacts\bin\{assemblyName}\{config}\{runtime}\{assemblyName}.xml";
return path;
}
In addition to this, the Configure method might look like:
public void Configure(IApplicationBuilder app)
{
...
app.UseSwaggerGen();
app.UseSwaggerUi();
...
}
Wen need to include two additional properties – host and schemes. Swagger specification clearly declares that both are NOT required. However, APIM DOES require both properties to be included in the swagger.json document.
So, how can we sort this out?
For your app in .NET 4.5+, just make sure that your SwaggerConfig.cs has activated those options with proper settings:
SwaggerDocsConfig.Schemes(new[] { “http”, “https” });
SwaggerDocsConfig.RootUrl(req => GetRootUrlFromAppConfig());
In your ASP.NET Core app, it might be tricky as you should implement the IDocumentFilter interface. Here’s a sample code:
public class SchemaDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Host = "localhost:44321";
swaggerDoc.BasePath = "/";
swaggerDoc.Schemes = new List<string>() { "https" };
}
}
And this SchemaDocumentFilter should be added into your ConfigureService method in Startup.cs:
public static void ConfigureServices(this IServiceCollection services)
{
...
services.AddSwaggerGen();
services.ConfigureSwaggerDocument(
options =>
{
options.SingleApiVersion(new Info() { Version = "v1", Title = "Swagger UI" });
options.IgnoreObsoleteActions = true;
options.OperationFilter(new ApplyXmlActionComments(GetXmlPath(appEnv)));
options.DocumentFilter<SchemaDocumentFilter>();
});
services.ConfigureSwaggerSchema(
options =>
{
options.DescribeAllEnumsAsStrings = true;
options.IgnoreObsoleteProperties = true;
options.CustomSchemaIds(type => type.FriendlyId(true));
options.ModelFilter(new ApplyXmlTypeComments(GetXmlPath(appEnv)));
});
...
}
Once you complete this, then import your swagger.json to APIM then it should work.
Reference:
Hope it helps.