question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Feature] DefaultValue for operation parameters defined by class

See original GitHub issue

Modify SwaggerGenerator so that it takes DefaultValueAttribute into account.

Given following operation:

/*
 * Matches following urls: 
 * /api/myresource/
 * /api/myresource?skip=10
 * /api/myresource?skip=10?take=20
 */
[HttpGet]
public IActionResult Index(MyQueryParams query)
{   
}

public class MyQueryParams
{
        [DefaultValue(0)]
        public int Skip { get; set; } = 0;

        [DefaultValue(10)]
        public int Top { get; set; } = 10;
}

Swashbucle should generate the parameters as Optional and with Default value:

 "get": {
    "parameters": [
        {
            "name": "skip",
            "in": "query",
            "required": false,
            "default": 0,
            "type": "integer",
            "format": "int32"
        },
        {
            "name": "top",
            "in": "query",
            "required": false,
            "default": 10,
            "type": "integer",
            "format": "int32"
        }
    ]
}

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:10
  • Comments:29 (7 by maintainers)

github_iconTop GitHub Comments

10reactions
whyleeecommented, Jan 24, 2018

@Liero you can add an operation filter as a quick fix, I wrote one that supports both property DefaultValue attributes and default values in method parameters:

// Adds Swagger support for optional parameters with default values
public class UpdateOptionalParamatersWithDefaultValues : IOperationFilter
{
    private readonly MvcJsonOptions _mvcJsonOptions;

    public UpdateOptionalParamatersWithDefaultValues(IOptions<MvcJsonOptions> mvcJsonOptions)
    {
        _mvcJsonOptions = mvcJsonOptions.Value;
    }

    public void Apply(Operation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null || !operation.Parameters.Any())
        {
            return;
        }

        var parameterValuePairs = context.ApiDescription.ParameterDescriptions
            .Where(parameter => GetDefaultValueAttribute(parameter) != null || GetParameterInfo(parameter).HasDefaultValue)
            .ToDictionary(parameter => parameter.Name, GetDefaultValue);

        foreach (var parameter in operation.Parameters)
        {
            if (parameterValuePairs.TryGetValue(parameter.Name, out var defaultValue))
            {
                parameter.Extensions.Add("default", defaultValue);
                parameter.Required = false;
            }
        }
    }

    private DefaultValueAttribute GetDefaultValueAttribute(ApiParameterDescription parameter)
    {
        if (!(parameter.ModelMetadata is DefaultModelMetadata metadata) || metadata.Attributes.PropertyAttributes == null)
        {
            return null;
        }

        return metadata.Attributes.PropertyAttributes
            .OfType<DefaultValueAttribute>()
            .FirstOrDefault();
    }

    public ParameterInfo GetParameterInfo(ApiParameterDescription parameter)
    {
        return ((ControllerParameterDescriptor) parameter.ParameterDescriptor).ParameterInfo;
    }

    private object GetDefaultValue(ApiParameterDescription parameter)
    {
        var parameterInfo = GetParameterInfo(parameter);

        if (parameterInfo.HasDefaultValue)
        {
            if (parameter.Type.IsEnum)
            {
                var stringEnumConverter = _mvcJsonOptions.SerializerSettings.Converters
                    .OfType<StringEnumConverter>()
                    .FirstOrDefault();

                if (stringEnumConverter != null)
                {
                    var defaultValue = parameterInfo.DefaultValue.ToString();
                    return stringEnumConverter.CamelCaseText ? ToCamelCase(defaultValue) : defaultValue;
                }
            }

            return parameterInfo.DefaultValue;
        }

        var defaultValueAttribute = GetDefaultValueAttribute(parameter);

        return defaultValueAttribute.Value;
    }

    private string ToCamelCase(string name)
    {
        return char.ToLowerInvariant(name[0]) + name.Substring(1);
    }
}
9reactions
jondmcelroycommented, Jan 10, 2019

Default Value Attribute is still ignored when being used as FromQuery in versions 4.0.1 and 5.0.0. @whyleee’s fix is very appreciated.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Swagger default value for parameter
I've always set the default on the param itself like this: public class TestPostController : ApiController { public decimal Get(decimal x ...
Read more >
Describing Parameters
In OpenAPI 3.0, parameters are defined in the parameters section of an operation or path. To describe a parameter, you specify its name...
Read more >
Named and Optional Arguments - C# Programming Guide
Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value...
Read more >
Parameters in UML class operations
A parameter has a type and it can have a default value. A parameter specifies the type of an argument and the value...
Read more >
Why I “hate” optional parameters in C# | by The Code ...
Optional does not mean Default. One of the biggest misuses of optional parameters is that of providing a default argument to a function....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found