7

I have Swagger/Swashbuckle integrated into a .NET Core 2.2 API project. Everything works great and what I am asking is purely for convenience. Consider the following API method:

public Model SomeEstimate(SomeRequest request) {
    return Manager.GetSomeEstimate(request);
}
...
public class SomeRequest {
    public string StreetAddress { get; set; }
    public string Zip { get; set; }
}

When I hit /swagger/index.html and want to try out this API, I always have to enter the StreetAddress and Zip values.

Is there a way to provide default values for StreetAddress and Zip? This answer suggested placing [DefaultValue("value here")] attribute each property of the SomeRequest class. It may have worked for the regular .NET, but not with .NET Core.

Is it possible to provide default values for parameters for the Swagger UI?

AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • 1
    See this link: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/575#issuecomment-461962745 .You would have to create a schema filter to achieve the DefaultValue attribute working in .NET Core – Rahul Sharma Mar 07 '19 at 19:39
  • @RahulSharma Excellent, that did the trick! – AngryHacker Mar 07 '19 at 20:10
  • Glad to hear that @AngryHacker. Shoud I post this as the answer to your question? – Rahul Sharma Mar 07 '19 at 20:14
  • @RahulSharma Do it so it's visible to whoever else has this question. – AngryHacker Mar 07 '19 at 20:18
  • 1
    See my answer to this similar question: https://stackoverflow.com/questions/57528575/swashbuckle-swagger-generate-an-actual-guid/57528916#57528916 – Paul Lorica Aug 16 '19 at 18:51
  • See my answer to this similar question: https://stackoverflow.com/questions/57528575/swashbuckle-swagger-generate-an-actual-guid/57528916#57528916 – Paul Lorica Aug 16 '19 at 18:52

6 Answers6

17

To define default values for parameters for Swagger UI in .NET Core, the following article defines a custom schema filter for your DefaultValue attribute in your Model class. The code shown below has been taken from this article and is purely to inform anyone else who has this question or has been facing a similar problem:

Decorate the desired properties in a model:

public class Test {
    [DefaultValue("Hello")]
    public string Text { get; set; }
}

Main filter:

using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Project.Swashbuckle {

    public class SchemaFilter : ISchemaFilter {

        public void Apply(Schema schema, SchemaFilterContext context) {
            if (schema.Properties == null) {
                return;
            }

            foreach (PropertyInfo propertyInfo in context.SystemType.GetProperties()) {

                // Look for class attributes that have been decorated with "[DefaultAttribute(...)]".
                DefaultValueAttribute defaultAttribute = propertyInfo
                    .GetCustomAttribute<DefaultValueAttribute>();

                if (defaultAttribute != null) {
                    foreach (KeyValuePair<string, Schema> property in schema.Properties) {

                        // Only assign default value to the proper element.
                        if (ToCamelCase(propertyInfo.Name) == property.Key) {
                            property.Value.Example = defaultAttribute.Value;
                            break;
                        }
                    }
                }
            }
        }

        private string ToCamelCase(string name) {
            return char.ToLowerInvariant(name[0]) + name.Substring(1);
        }
    }
}

And finally registering it to your Swagger Options(In Startup.cs):

services.AddSwaggerGen(c => {
    // ...
    c.SchemaFilter<SchemaFilter>();
});
Rahul Sharma
  • 7,768
  • 2
  • 28
  • 54
  • Any idea how to provide default values for [parameters with FromQuery attribute](https://stackoverflow.com/questions/56065200/how-to-define-default-values-for-fromquery-parameters-for-the-swagger-ui)? – AngryHacker May 09 '19 at 18:06
  • @AngryHacker See this question: https://stackoverflow.com/questions/55375960/how-to-set-two-default-fields-to-my-input-model-on-asp-net-webapi-net-core#comment97496730_55375960 – Rahul Sharma May 10 '19 at 09:42
10

The initial credit goes to Rahul Sharma, though if someone is interested in .NET Core 3.0+, Swashbuckle v5.0.0-rc4 makes the SchemaFilter definition much simpler. Maybe there's a way to add example value with a new attribute or something like that, but I haven't found such a way.

public class SchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (schema.Properties == null)
        {
            return;
        }

        foreach (var property in schema.Properties)
        {
            if (property.Value.Default != null && property.Value.Example == null)
            {
                property.Value.Example = property.Value.Default;
            }
        }
    }
}
Max Shnurenok
  • 141
  • 1
  • 3
8

Swashbuckle.AspNetCore 5.6.3 needs just DefaultValueAttribute.

xhafan
  • 2,140
  • 1
  • 26
  • 26
3

Swashbuckle.AspNetCore 5.6.3 needs just System.ComponentModel.DefaultValueAttribute like so:

[System.ComponentModel.DefaultValue((int)DateTypeEnum.CreationDate)]
public int DateType{ get; set; }

For reference type properties like datetime type, you cannot use the System.ComponentModelDefaultValueAttribute since it does not support a reference type initialize. For this case I created a custom default value attribute that get a string value and convert it to a primitive type. then I defined a schema filter that set the value into the default memberInfo schema:

  1. DefaultValueAttribute
  public class DefaultValueAttribute : Attribute
    {
        public IOpenApiPrimitive Value { get; set; }


        public DefaultValueAttribute(PrimitiveType type, string value = "")
        {
            SetValue(type, value);
        }

        public DefaultValueAttribute(PrimitiveType type = PrimitiveType.DateTime, int addYears = 0, int addDays = 0, int addMonths = 0)
        {
            SetValue(type, "", addYears, addDays, addMonths);
        }

        private void SetValue(PrimitiveType Type, string value = "", int addYears = 0, int addDays = 0, int addMonths = 0)
        {
            switch (Type)
            {
                case PrimitiveType.Integer:
                    Value = new OpenApiInteger(Convert.ToInt32(value));
                    break;
                case PrimitiveType.Long:
                    Value = new OpenApiLong(Convert.ToInt64(value));
                    break;
                case PrimitiveType.Float:
                    Value = new OpenApiFloat(Convert.ToUInt64(value));
                    break;
                case PrimitiveType.Double:
                    Value = new OpenApiDouble(Convert.ToDouble(value));
                    break;
                case PrimitiveType.String:
                    Value = new OpenApiString(value);
                    break;
                case PrimitiveType.Byte:
                    Value = new OpenApiByte(Convert.ToByte(value));
                    break;
                case PrimitiveType.Binary:
                    Value = new OpenApiBinary(value.ToCharArray().Select(c => Convert.ToByte(c)).ToArray());
                    break;
                case PrimitiveType.Boolean:
                    Value = new OpenApiBoolean(Convert.ToBoolean(value));
                    break;
                case PrimitiveType.Date:
                    break;
                case PrimitiveType.DateTime:
                    Value = new OpenApiDate(DateTime.Now.AddYears(addYears).AddDays(addDays).AddMonths(addMonths));
                    break;
                case PrimitiveType.Password:
                    Value = new OpenApiPassword(value);
                    break;
                default:
                    break;
            }
        }

    }

  1. SchemaFilter
 public class DefaultValuesSwaggerExtensions : Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            var attributes = context?.MemberInfo?.GetCustomAttributes(true).OfType<DefaultValueAttribute>();

            if (attributes?.Any() == true)
            {
                schema.Default = attributes.First().Value;
            }
        }
    }
  1. Add the filter to Swagger
 services.AddSwaggerGen(c =>
            {
                c.SchemaFilter<DefaultValuesSwaggerExtensions>();
            });
  1. add the attribute to the property
 [DTOs.Common.DefaultValue(Microsoft.OpenApi.Any.PrimitiveType.DateTime, -1)]
  public DateTime FromDate { get; set; } = DateTime.Now.AddYears(-1);
ayala
  • 331
  • 1
  • 9
1

For value types you can use just System.ComponentModel.DefaultValueAttribute like so:

[System.ComponentModel.DefaultValue((int)DateTypeEnum.CreationDate)]
public int DateType{ get; set; }

For primitive type property like datetime type, you cannot add a default value in the System.ComponentModelDefaultValueAttribute since attribute does not support a reference type initialize. For this case I created a custom default value attribute that get a string value and convert it to a primitive type. then I defined a schema filter that set the value into the default memberInfo schema:

  1. DefaultValueAttribute
  public class DefaultValueAttribute : Attribute
    {
        public IOpenApiPrimitive Value { get; set; }


        public DefaultValueAttribute(PrimitiveType type, string value = "")
        {
            SetValue(type, value);
        }

        public DefaultValueAttribute(PrimitiveType type = PrimitiveType.DateTime, int addYears = 0, int addDays = 0, int addMonths = 0)
        {
            SetValue(type, "", addYears, addDays, addMonths);
        }

        private void SetValue(PrimitiveType Type, string value = "", int addYears = 0, int addDays = 0, int addMonths = 0)
        {
            switch (Type)
            {
                case PrimitiveType.Integer:
                    Value = new OpenApiInteger(Convert.ToInt32(value));
                    break;
                case PrimitiveType.Long:
                    Value = new OpenApiLong(Convert.ToInt64(value));
                    break;
                case PrimitiveType.Float:
                    Value = new OpenApiFloat(Convert.ToUInt64(value));
                    break;
                case PrimitiveType.Double:
                    Value = new OpenApiDouble(Convert.ToDouble(value));
                    break;
                case PrimitiveType.String:
                    Value = new OpenApiString(value);
                    break;
                case PrimitiveType.Byte:
                    Value = new OpenApiByte(Convert.ToByte(value));
                    break;
                case PrimitiveType.Binary:
                    Value = new OpenApiBinary(value.ToCharArray().Select(c => Convert.ToByte(c)).ToArray());
                    break;
                case PrimitiveType.Boolean:
                    Value = new OpenApiBoolean(Convert.ToBoolean(value));
                    break;
                case PrimitiveType.Date:
                    break;
                case PrimitiveType.DateTime:
                    Value = new OpenApiDate(DateTime.Now.AddYears(addYears).AddDays(addDays).AddMonths(addMonths));
                    break;
                case PrimitiveType.Password:
                    Value = new OpenApiPassword(value);
                    break;
                default:
                    break;
            }
        }

    }

  1. SchemaFilter
 public class DefaultValuesSwaggerExtensions : Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            var attributes = context?.MemberInfo?.GetCustomAttributes(true).OfType<DefaultValueAttribute>();

            if (attributes?.Any() == true)
            {
                schema.Default = attributes.First().Value;
            }
        }
    }
  1. Add the filter to Swagger
 services.AddSwaggerGen(c =>
            {
                c.SchemaFilter<DefaultValuesSwaggerExtensions>();
            });
  1. use the attribute on the property
 [DTOs.Common.DefaultValue(Microsoft.OpenApi.Any.PrimitiveType.DateTime, -1)]
  public DateTime FromDate { get; set; } = DateTime.Now.AddYears(-1);
ayala
  • 331
  • 1
  • 9
1

Here is what worked for me

public class ExternalJobCreateViewModel
{
    ///<example>Bob</example>
    public string CustomFilename { get; set; }

    ///<example>false</example>
    public bool IsUrgent { get; set; }

    ///<example>false</example>
    public bool IsMultiSpeaker { get; set; }

    ///<example></example>
    public string JobInstruction { get; set; }

    ///<example></example>
    public string Url { get; set; }
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 27 '23 at 20:47