Default model example in Swashbuckle (Swagger)
I know this thread is quite old, but I wanted to share my solution which creates a custom constructor just for the Swagger example schema.
In my model:
/// <summary>
/// Supply a custom constructor for Swagger where you can apply defaults to control the example schema.
/// The constructor must have one parameter of type System.Reflection.ParameterInfo[].
/// Note: Setting a property to null will prevent it from showing in the Swagger example.
/// </summary>System.Reflection.ParameterInfo[].
/// </summary>
public class SwaggerConstructor : Attribute { }
In SwaggerConfig.cs:
c.SchemaFilter<ApplySchemaVendorExtensions>();
The schema extension:
public class ApplySchemaVendorExtensions : ISchemaFilter
{
public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
{
ConstructorInfo constructor = type.GetConstructors().FirstOrDefault(c => c.GetCustomAttribute<SwaggerConstructor>() != null);
if (constructor != null)
{
schema.example = constructor.Invoke(new object[] { constructor.GetParameters() });
}
}
}
Usage:
[SwaggerConstructor]
public MyClass(System.Reflection.ParameterInfo[] decoy) : base()
{
MyProperty = false;
}
An example Model Schema can be defined by implementing ISchemaFilter
and registering it using the following:
httpConfig
.EnableSwagger(c =>
{
c.SchemaFilter<AddSchemaExamples>()
});
An example implementation is provided here:
public class AddSchemaExamples : ISchemaFilter
{
public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
{
if (type == typeof(Product))
{
schema.example = new Product
{
Id = 123,
Type = ProductType.Book,
Description = "Treasure Island",
UnitPrice = 10.0M
};
}
}
}
Source: https://github.com/domaindrivendev/Swashbuckle/issues/162
Well the code of vgaspar.trivix did not work completly for me, the default values did not get set for the schema. Also i got an NullPointerException
. I managed to get it working as intended by editing the Apply
method and manipulated the schemaRegistry like this:
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
return;
IDictionary<string, object> parameterValuePairs =
GetParameterValuePairs(apiDescription.ActionDescriptor);
foreach (var param in operation.parameters)
{
if (param.schema != null && param.schema.@ref != null)
{
string schemaName = [email protected]('/').LastOrDefault();
if (schemaRegistry.Definitions.ContainsKey(schemaName))
foreach (var props in schemaRegistry.Definitions[schemaName].properties)
{
if (parameterValuePairs.ContainsKey(props.Key))
props.Value.@default = parameterValuePairs[props.Key];
}
}
var parameterValuePair = parameterValuePairs.FirstOrDefault(p => p.Key.IndexOf(param.name, StringComparison.InvariantCultureIgnoreCase) >= 0);
param.@default = parameterValuePair.Value;
}
}
I managed to get this working by following what's on this link:
https://github.com/domaindrivendev/Swashbuckle/issues/69#issuecomment-53953785
In short this is what needs to be done:
Create the classes SwaggerDefaultValue and AddDefaultValues as described in the link. Some changes that I did:
public class SwaggerDefaultValue : Attribute { public string Name { get; set; } public string Value { get; set; } public SwaggerDefaultValue(string value) { this.Value = value; } public SwaggerDefaultValue(string name, string value) : this(value) { this.Name = name; } } public class AddDefaultValues : IOperationFilter { public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { IDictionary<string, object> parameterValuePairs = GetParameterValuePairs(apiDescription.ActionDescriptor); foreach (var param in operation.parameters) { var parameterValuePair = parameterValuePairs.FirstOrDefault(p => p.Key.IndexOf(param.name, StringComparison.InvariantCultureIgnoreCase) >= 0); param.@default = parameterValuePair.Value; } } private IDictionary<string, object> GetParameterValuePairs(HttpActionDescriptor actionDescriptor) { IDictionary<string, object> parameterValuePairs = new Dictionary<string, object>(); foreach (SwaggerDefaultValue defaultValue in actionDescriptor.GetCustomAttributes<SwaggerDefaultValue>()) { parameterValuePairs.Add(defaultValue.Name, defaultValue.Value); } foreach (var parameter in actionDescriptor.GetParameters()) { if (!parameter.ParameterType.IsPrimitive) { foreach (PropertyInfo property in parameter.ParameterType.GetProperties()) { var defaultValue = GetDefaultValue(property); if (defaultValue != null) { parameterValuePairs.Add(property.Name, defaultValue); } } } } return parameterValuePairs; } private static object GetDefaultValue(PropertyInfo property) { var customAttribute = property.GetCustomAttributes<SwaggerDefaultValue>().FirstOrDefault(); if (customAttribute != null) { return customAttribute.Value; } return null; } }
Edit your SwaggerConfig and add the AddDefaultValues class to the OperationFilters:
GlobalConfiguration.Configuration .EnableSwagger(c => { ... c.OperationFilter<AddDefaultValues>() ... });
Now for the parameters I want default values I just add the following:
public IHttpActionResult Put([FromBody]Pet pet) { ... return Ok(); } public class Pet { [SwaggerDefaultValue("doggie")] public string Name { get; set; } [SwaggerDefaultValue("available")] public string Status; ... }