5
public class InputModel
{
    public string Thing { get; set; }
    public DateTime AnotherThing { get; set; }
}

public ThingController : ControllerBase
{
    public Task DoTheThing([FromQuery] int foo, [FromQuery] InputModel input)
    {
        // Elided.
    }
}

The problem is that when the Swagger documentation is generated for this controller, the following inputs are listed for DoTheThing:

foo: int
Thing: string
AnotherThing: DateTime

Note how the last two inputs start with uppercase, because that's how they are defined in their model. I want them to start with lowercase to be consistent with the non-complex parameters passed to the controller method (remember, ASP.NET model binding doesn't care about casing).

The easy way to do this is to either have those properties be named starting with lowercase on the model, or apply the FromQuery and/or FromBody attribute on them. I don't want to do either of these things because the former is just nasty, and the latter is applying behaviour to properties, when I need that behaviour to be applied on a case-by-case basis.

Ideally I'd like to be able to write something like the following (which currently doesn't work because Swashbuckle doesn't seem to know/care about the DisplayName or Display attributes):

public class InputModel
{
    [DisplayName("thing")]
    public string Thing { get; set; }
    [DisplayName("anotherThing")]
    public DateTime AnotherThing { get; set; }
}

However, I'd be happy with any solution that allows me to "rename" the model properties without changing their names.

I have looked at Swashbuckle.AspNetCore.Annotations but it doesn't appear to provide this functionality.

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138

2 Answers2

3

To force all parameters to be lowercase, use the obviously-named but poorly-documented DescribeAllParametersInCamelCase method:

services.AddSwaggerGen(o =>
{
    ...
    o.DescribeAllParametersInCamelCase();
    ...
});

(This ended up being somewhat of an XY question, because what I wanted was a way to force all params to be described as lowercase, but couldn't find a way to do it, so I asked for a general way to modify param names.)

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
0

You can achieve that with a IDocumentFilter in Asp.Net Core, i am not sure that this will work in normal Asp.Net but the solution must be similar.

The DocumentFilter iterates all parameters and lowers the first letter.

using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

/// <summary>
/// A DocumentFilter that lowers the first letter of the query parameters.
/// </summary>
public class NameDocumentFilter : IDocumentFilter
{
    #region explicit interfaces

    /// <inheritdoc />
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        if (swaggerDoc.Paths.Count <= 0)
        {
            return;
        }
        foreach (var path in swaggerDoc.Paths.Values)
        {
            ToLower(path.Parameters);

            // Edit this list if you want other operations.
            var operations = new List<Operation>
            {
                path.Get,
                path.Post,
                path.Put
            };
            operations.FindAll(x => x != null)
                .ForEach(x => ToLower(x.Parameters));
        }
    }

    #endregion

    #region methods

    /// <summary>
    /// Lowers the first letter of a parameter name.
    /// </summary>
    private static void ToLower(IList<IParameter> parameters)
    {
        if (parameters == null)
        {
            return;
        }
        foreach (var param in parameters)
        {
            // limit the renaming only to query parameters
            if (!param.In.Equals("query", StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }
            // shouldn't happen, just to make sure
            if (string.IsNullOrWhiteSpace(param.Name))
            {
                continue;
            }
            param.Name = param.Name[0]
                             .ToString()
                             .ToLower() + param.Name.Substring(1);
        }
    }

    #endregion
}

Then register die DocumentFilter in the swagger configuration:

services.AddSwaggerGen(
            c =>
            {
                c.SwaggerDoc(
                    "v1",
                    new Info
                    {
                        Title = "My WebSite",
                        Version = "v1"
                    });
                c.DocumentFilter<NameDocumentFilter>();
            });

I adjusted this code from a sample that describes enum parameters, but the same idea works for renaming.

Rabban
  • 2,451
  • 1
  • 19
  • 21