I\'m using Swashbuckle to generate swagger documentation\\UI for a webapi2 project. Our models are shared with some legacy interfaces so there are a couple of properties I
Based on Stef Heyenrath's answer.
Attribute to mark properties to exclude from the Swagger documentation.
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute
{
}
The filter to exclude the properties from the Swagger documentation.
public class SwaggerExcludeSchemaFilter : ISchemaFilter
{
public void Apply(Schema schema, SchemaFilterContext context)
{
if (schema?.Properties == null)
{
return;
}
var excludedProperties =
context.SystemType.GetProperties().Where(
t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null);
foreach (var excludedProperty in excludedProperties)
{
var propertyToRemove =
schema.Properties.Keys.SingleOrDefault(
x => x.ToLower() == excludedProperty.Name.ToLower());
if (propertyToRemove != null)
{
schema.Properties.Remove(propertyToRemove);
}
}
}
}
The schema.Properties.Keys
are camelCase
, while the properties themselves are PascalCase
. Tweaked the method to convert both to lower case and compare to see what should be excluded.
The code below is very much based on @Richard's answer, but I am including it as a new answer because it has three completely new, useful features which I have added:
SwaggerIgnore
attribute to be applied to fields not just to propertiesJsonProperty
attributeSo the revised code is:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SwaggerIgnoreAttribute : Attribute
{
}
internal static class StringExtensions
{
internal static string ToCamelCase(this string value)
{
if (string.IsNullOrEmpty(value)) return value;
return char.ToLowerInvariant(value[0]) + value.Substring(1);
}
}
public class SwaggerIgnoreFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext schemaFilterContext)
{
if (schema.Properties.Count == 0)
return;
const BindingFlags bindingFlags = BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance;
var memberList = schemaFilterContext.SystemType
.GetFields(bindingFlags).Cast<MemberInfo>()
.Concat(schemaFilterContext.SystemType
.GetProperties(bindingFlags));
var excludedList = memberList.Where(m =>
m.GetCustomAttribute<SwaggerIgnoreAttribute>()
!= null)
.Select(m =>
(m.GetCustomAttribute<JsonPropertyAttribute>()
?.PropertyName
?? m.Name.ToCamelCase()));
foreach (var excludedName in excludedList)
{
if (schema.Properties.ContainsKey(excludedName))
schema.Properties.Remove(excludedName);
}
}
}
and in Startup.cs
:
services.AddSwaggerGen(c =>
{
...
c.SchemaFilter<SwaggerIgnoreFilter>();
...
});
I get inspired by the blog of Ignoring properties from controller action model in Swagger using JsonIgnore.
I'm using .net core 2.1
and Swashbuckle.AspNetCore 5.3.1
.
The code below solved the problem.
Add a new filter
public class SwaggerJsonIgnoreFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var ignoredProperties = context.MethodInfo.GetParameters()
.SelectMany(p => p.ParameterType.GetProperties()
.Where(prop => prop.GetCustomAttribute<JsonIgnoreAttribute>() != null))
.ToList();
if (!ignoredProperties.Any()) return;
foreach (var property in ignoredProperties)
{
operation.Parameters = operation.Parameters
.Where(p => (!p.Name.Equals(property.Name, StringComparison.InvariantCulture)))
.ToList();
}
}
}
Use the Filter in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
......
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "CustomApi", Version = "v1" });
options.OperationFilter<SwaggerJsonIgnoreFilter>();
});
......
}
I have here a working example with DotNetCore 3 and Swashbuckle 5. It took me a few hours to get it in place so I thought to come back to this thread which helped me but didn't solve my issue.
Create a dummy custom attribute:
[AttributeUsage(AttributeTargets.Property)]
public class SwaggerExcludeAttribute : Attribute { }
Create a SchemaFilter which will be used by swagger to generate the API Model Schema
public class SwaggerExcludeFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (!(context.ApiModel is ApiObject))
{
return;
}
var model = context.ApiModel as ApiObject;
if (schema?.Properties == null || model?.ApiProperties == null)
{
return;
}
var excludedProperties = model.Type
.GetProperties()
.Where(
t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null
);
var excludedSchemaProperties = model.ApiProperties
.Where(
ap => excludedProperties.Any(
pi => pi.Name == ap.MemberInfo.Name
)
);
foreach (var propertyToExclude in excludedSchemaProperties)
{
schema.Properties.Remove(propertyToExclude.ApiName);
}
}
}
Then, inside the Startup.cs
file add this to the swagger configuration
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SchemaFilter<SwaggerExcludeFilter>();
});
You can now use the custom attribute on a property that you want to exclude from the API Mode Shema like this
public class MyApiModel
{
[SwaggerExclude]
public Guid Token { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
Referring to https://stackoverflow.com/a/58193046/11748401 answer, for creating a filter you can simply use the following code:
public class SwaggerExcludeFilter : ISchemaFilter
{
public void Apply(OpenApiSchema model, SchemaFilterContext context)
{
var excludeProperties = context.ApiModel.Type?.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(SwaggerExcludeAttribute)));
if (excludeProperties != null)
{
foreach (var property in excludeProperties)
{
// Because swagger uses camel casing
var propertyName = $"{ToLowerInvariant(property.Name[0])}{property.Name.Substring(1)}";
if (model.Properties.ContainsKey(propertyName))
{
model.Properties.Remove(propertyName);
}
}
}
}
}
The AspNetCore
solution looks like:
public class SwaggerExcludeSchemaFilter : ISchemaFilter
{
public void Apply(Schema schema, SchemaFilterContext context)
{
if (schema?.Properties == null)
{
return;
}
var excludedProperties = context.SystemType.GetProperties().Where(t => t.GetCustomAttribute<SwaggerExcludeAttribute>() != null);
foreach (PropertyInfo excludedProperty in excludedProperties)
{
if (schema.Properties.ContainsKey(excludedProperty.Name))
{
schema.Properties.Remove(excludedProperty.Name);
}
}
}
}