Swagger documentation: Swashbuckle (hide methods/properties) - swagger

I am using Swagger Swashbuckle to generate documentation. There are some methods in my controller and some properties in my models that I don't want to document.
Is there any arrtibute or the property to leave or ignore specific methods from documentation?

For the method, you have couple of option:
Use Obsolete attribute. Then, you have to set the action - c.IgnoreObsoleteActions(); within the swagger configuration
Create a custom attribute and a swagger document filter. The document filter should iterate through each method and remove the method documentation if the method is having the custom attribute
For the properties, you can use JsonIgnoreAttribute

In addition to c.IgnoreObsoleteActions(), there is also c.IgnoreObsoleteProperties(), which hides the property from the documentation.
JsonIgnoreAttribute will stop the property deserializing when being received as part of a POST request body, which may not be what you want if you only wish to change the documentation and not the functionality.

In more recent version of Swashbuckle (Core2/3) XmlIgnore/JsonIgnore don't seem to work for properties.
Alternatively you can change the property access modifier to internal. This should prevent serialization and generated documentation.
I'm not sure about hiding whole controllers, you will probably need to add filters in your Swagger setup. I do have an example of hiding certain endpoints (for convenience I have prefixed routes for running locally):
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen(config => {
config.SwaggerDoc("v1",
new OpenApiInfo {
Version = "v1",
Title = "Foo API",
Description = "Does foo things.",
Contact = new OpenApiContact {
Name = "nope",
Email = "mail#example.org",
},
});
// Include XML comments in Swagger docs
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
config.IncludeXmlComments(xmlPath);
// Filter out prefixed routes
config.DocInclusionPredicate(
(name, desc) => !desc.RelativePath.ToLower().StartsWith("MyDevPrefix"));
});
}

Just a note since I was also trying to figure out the JsonIgnore for properties not working...
The issue seems to be that newer versions of Swashbuckle for .Net Core do not support NewtonSoft out of the box.
Install from NuGet
Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft -Version 5.6.2
CLI : dotnet add package --version 5.6.2 Swashbuckle.AspNetCore.Newtonsoft
Add code to startup.cs
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()
This worked for me, hope this helps someone else.

Here's a bit newer answer:
As other's mentioned - to ignore properties (both docs and real response) use attribute: [JsonIgnore]
To hide controller/actions from docs (the controller/action still exists, it is just hidden from docs) use attribute: [ApiExplorerSettings(IgnoreApi = true)]

Related

Swashbuckle.AspNet.Core: Swagger UI shows empty page - How to fix?

I added Swashbuckle.AspNet.Core to my repository and initialized everything using the default values.
Although I can see JSON output from /swagger/v1/swagger.json opening /swagger/index.html just yields an empty page.
Why?
Here's my code
public void ConfigureServices(IServiceCollection services)
{
services
.AddSwaggerGen()
.AddControllers()
;
}
// This method gets called by the runtime once. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, Options options)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app
.UseHttpsRedirection()
.UseRouting()
.UseAuthorization()
.UseEndpoints(endpoints => endpoints.MapControllers())
.UseSwagger()
;
if (env.IsDevelopment()) app.UseSwaggerUI();
}
You haven't configured your Swashbuckle service correctly.
In your configureServices method, the call to AddSwaggerGen has "optional parameters", so the way you've specified it will work, but it's more common to do the following:
services.AddSwaggerGen(config =>
{
config.SwaggerDoc("v1", new OpenApiInfo() { Title = "Payment Card Info API", Version = "v1" });
});
Title is the title your Swagger Doc will show, and version is the advertised version of your API as displayed on your document, the FIRST "v1" parameter, is the version parameter that will be used in the actual swagger URL used to server the json file.
The code you place in your "Configure" method however, is NOT optional and must be done in a specific way.
app.UseSwagger();
app.UseSwaggerUI(config =>
{
config.SwaggerEndpoint("/swagger/v1/swagger.json", "Payment Card Info API");
});
The "UseSwaggerUI call MUST be configured manually, as it appears the defaults in the code simply don't work automatically.
By default your swagger json doc will always be at "/swagger/" + first version parameter in swaggerDoc call + "/swagger.json" (This can be changed, but I wouldn't recommend it)
Your swagger endpoint call, must be the actual URL the json is served at and a name of your choice to label it.
I would also strongly suggest wrapping your UseSwaggerUI call in an "env.IsDevelopment" call so that it's automatically turned off when you do a production build of your app, and thus will not make it available once your service is deployed.
Here's how I've done mine.

Multiple swagger JSON file generation for different API groups

I have swagger configured in my solution and it is showing up the API documentation properly. Now recently I have developed some new APIs in the same solution and these are also showing up in API documentation and these projects also follow the same naming conventions.
Now my requirement is I want to segregate the new API documentation from the older ones so basically I want two JSON files generated one foe each, old API, AND new API.
My Swagger configuration looks like the following.
Config.EnableSwagger(#"api-docs/{apiVersion}",
c =>
{
c.SingleApiVersion("v1", "SAMPLE API");
c.UseFullTypeNameInSchemaIds();
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
foreach (String x in Directory.GetFiles(Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)), "*.dll")
.Where(f => Path.GetFileNameWithoutExtension(f).ToLower().Contains("sample") ****&& !Path.GetFileNameWithoutExtension(f).ToLower().Contains("sample.api"))****
.Select(f => String.Format(#"{0}\{1}.xml", Path.GetDirectoryName(f), Path.GetFileNameWithoutExtension(f)))
.Where(File.Exists))
{
c.IncludeXmlComments(x);
}
c.OperationFilter<AddRequiredHeaderParameter>();
});
My New API projects are named sample.api.test and old API projects are named sample.web.test.
I added the && part in the where clause to ignore picking my new files in the first JSON doc generation but of no luck. I am new to this and really don't know if it is possible to have two JSON depending on project names. Any help would be greatly appreciated.
I fixed this using IDocumentFilter as follows.
internal class SwaggerFilterOutControllers : IDocumentFilter
{
void IDocumentFilter.Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
var apiKeys = swaggerDoc.paths.Select(s => s.Key).ToList();
foreach (var apiKey in apiKeys)
{
if (swaggerDoc.info.title == "old API" && apiKey.StartsWith("/latapi"))
swaggerDoc.paths.Remove(apiKey);
else if (swaggerDoc.info.title == "New Public API" && !apiKey.StartsWith("/latapi"))
swaggerDoc.paths.Remove(apiKey);
}
}
}
and then in the enableswagger() method i called this filter as
c.DocumentFilter<SwaggerFilterOutControllers>();

Issue Using Custom Index.Html in Swagger / Swashbuckle for .NET Core

I am having difficulty using a custom index.html and other assets with swashbuckle. Swashbuckle/Swagger do not seem to recognizing or using them at all. I do have app.UseDefaultFiles() and app.UseStaticFiles() set. I am trying to understand what I am doing incorrectly.
I have attempted to set up my configuration somewhat similar to what is defined on the Microsoft article without success. (https://learn.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio)
I am presently using the files from the dist folder referenced in the article (https://github.com/swagger-api/swagger-ui/tree/2.x/dist) along with the custom css file provided.
My index.html file is located under /wwwroot/swagger/ui
The custom css file is located under /wwwroot/swagger/ui/css (as custom.css)
Here is my Startup.cs class.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options =>
{
// Swagger - Format JSON
options.SerializerSettings.Formatting = Formatting.Indented;
});
// Register the Swagger generator, defining one or more Swagger documents
services.AddSwaggerGen(c =>
{
c.DescribeAllEnumsAsStrings();
c.DescribeStringEnumsInCamelCase();
// c.DescribeAllParametersInCamelCase();
c.SwaggerDoc("v1",
new Info
{
Title = "My Web API - v1",
Version = "v1",
Description = "New and improved version. A simple example ASP.NET Core Web API. "
}
);
c.SwaggerDoc("v2",
new Info
{
Title = "My Web API - v2",
Version = "v2",
Description = "New and improved version. A simple example ASP.NET Core Web API. "
}
);
// Set the comments path for the Swagger JSON and UI.
var basePath = AppContext.BaseDirectory;
var xmlPath = Path.Combine(basePath, "ApiTest.xml");
c.IncludeXmlComments(xmlPath);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
string swaggerUIFilesPath = env.WebRootPath + "\\swagger\\ui";
if (!string.IsNullOrEmpty(swaggerUIFilesPath))
{
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(swaggerUIFilesPath),
RequestPath = new PathString("/api-docs"),
});
}
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger(c =>
{
c.RouteTemplate = "api-docs/{documentName}/swagger.json";
});
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
//c.ShowJsonEditor();
c.RoutePrefix = "api-docs";
c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My Web API - V1 ");
c.SwaggerEndpoint("/api-docs/v2/swagger.json", "My Web API - V2 ");
c.DocumentTitle("My Web API");
});
app.UseMvc();
}
}
My ultimate objective is to be able to use something like the slate style theme available here (https://github.com/omnifone/slate-swagger-ui). For right now, I am just trying to get Swashbuckle/Swagger to use the customized files referenced in the Microsoft documentation before trying to make the other files work.
I really do NOT want to try and convert my assets to embedded resources--since there will many of them. I just want to reference a normal index.html file and be able to use all of its referenced files.
What am I doing wrong?
Relevant Software Versions
.Net Core Version: 2.0.3
Swashbuckle.AspNetCore: 1.2.0
Windows 10 Enterprise Build 1703
Visual Studio 2017 Enterprise 15.5.2
Here is the minimum action I found to be necessary to replace SwashBuckle's index.html in a .NET Core project:
Get a copy of the original index.html from here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerUI/index.html
Place that copy in some sub-folder of your project.
The file may have a different name, I chose:
\Resources\Swagger_Custom_index.html
Right-click that file in Solution Explorer, select 'Properties', select 'Configuration Properties' in left pane. Under 'Advanced' in right pane find entry 'Build Action' and set it to 'Embedded resource'. Click Ok.
In Startup.cs add the following line to your app.UseSwaggerUI() call:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
app.UseSwaggerUI(c =>
{
c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Your.Default.Namespace.Resources.Swagger_Custom_index.html");
});
//...
}
The identifier for the file resource in the above GetManifestResourceStream method is composed of:
your default namespace (i.e. 'Your.Default.Namespace')
the sub-path of your resource (i.e. 'Resources')
the filename of your resource (i.e. 'Swagger_Custom_index.html')
All three parts are concatenated using dots (NO slashes or backslashes here).
If you don't use a sub-path but have your resource in root, just omit part 2.
For people who separate ApplicationBuilder config methods on ASP.NET Core:
If the separated method/class is static, it is not possible to call GetType() because an object reference is required.
In that case, switch GetType() to MethodBase.GetCurrentMethod().DeclaringType
c.IndexStream = () => MethodBase.GetCurrentMethod().DeclaringType.Assembly.GetManifestResourceStream("xxx.index.html");

MVC email template engine .netcoreapp1.1

I'm new with ASP.NET Core and I am trying to make emails, based on templates.
I want to include tags, which are then replaced with specific data from the controller.
I found a engine called razorengine that was exectly what I was looking for, but it is not compatible with .netcoreapp1.1. Are there other alternatives that I could use?
I am using Mailkit btw.
UPDATE:
I found a alternative called DotLiquid, Thanks anyways!
You may also use RazorLight which allows the same using the built-in Razor engine and runs with .Net Core.
You don't need to include an extra library for that.
Just create an html file that lies in your project scope and mark your placeholders e.g. via {{ ... }}
For example create a file wwwroot/emails/welcome.html:
Dear {{user}},
<p>Have fun with this page.</p>
<p>Please click here to activate your account.</p>
Best wishes
Now in your controller action:
public async Task<IActionResult> SendSomeEmailTo(userId)
{
string body;
using (var file = System.IO.File.OpenText("wwwroot/emails/welcome.html"))
{
body = file.ReadToEnd();
}
var user = this.userManager.findById(userId);
// replace your placeholders here
body = body
.Replace("{{user}}", user.getFullName())
.Replace("{{link}}", "www.foo.bar");
// use the email body in your email service of your choice
await sender.SendEmailAsync(user.Email, "Welcome", body);
}

Swagger 2.0 where to declare Basic Auth Schema

How do I define basic authentication using Swagger 2.0 annotations and have it display in swagger UI.
In the resource I have:
#ApiOperation(value = "Return list of categories", response=Category.class, responseContainer="List", httpMethod="GET", authorizations = {#Authorization(value="basicAuth")})
public Response getCategories();
I looked here:
https://github.com/swagger-api/swagger-core/wiki/Annotations#authorization-authorizationscope
And it says "Once you've declared and configured which authorization schemes you support in your API, you can use these annotation to note which authorization scheme is required on a resource or a specific operation" But I can't find anything that talks about where to declare and configure the authorization schemes.
Update:
I found code on how to declare the schema, but I still do not see any information about the authentication schema in the UI. I'm not sure what I am missing
#SwaggerDefinition
public class MyApiDefinition implements ReaderListener {
public static final String BASIC_AUTH_SCHEME = "basicAuth";
#Override
public void beforeScan(Reader reader, Swagger swagger) {
}
#Override
public void afterScan(Reader reader, Swagger swagger) {
BasicAuthDefinition basicAuthDefinition = new BasicAuthDefinition();
swagger.addSecurityDefinition(BASIC_AUTH_SCHEME, basicAuthDefinition);
}
}
Using Springfox 2.6 annotations, you must first define Basic authentication as one of the security schemes when you set up the Docket in your configuration, like this:
List<SecurityScheme> schemeList = new ArrayList<>();
schemeList.add(new BasicAuth("basicAuth"));
return new
Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo)
.securitySchemes(schemeList)
...
Then you can use the Springfox annotations in your service to set Basic Auth for the operation for which you want to require authentication:
#ApiOperation(value = "Return list of categories", response=Category.class, responseContainer="List", httpMethod="GET", authorizations = {#Authorization(value="basicAuth")})
public Response getCategories();
I struggeled with this as well. In my case i used the swagger-maven-plugin. To solve this i added this within the maven plugin:
<securityDefinitions>
<securityDefinition>
<name>basicAuth</name>
<type>basic</type>
</securityDefinition>
</securityDefinitions>
After that i was able to add it on my resource like this:
#Api(value = "My REST Interface", authorizations = {#Authorization(value="basicAuth")})
The generated json included the security element for each endpoint:
"security":[{
"basicAuth" : []
}]
And the security definition:
"securityDefinitions" : {
"basicAuth" : {
"type" : "basic"
}
}
I hope this helps others as well.
You can use the #SwaggerDefinition
http://swagger.io/customizing-your-auto-generated-swagger-definitions-in-1-5-x/
or you can configure the swagger object directly, here's an example
http://www.programcreek.com/java-api-examples/index.php?source_dir=rakam-master/rakam/src/main/java/org/rakam/WebServiceRecipe.java

Resources