是否可以在不使用 FromQuery 的情况下在 Swagger UI 中为输入模型属性指定不同的名称?

Is it possible to give input model properties different names in the Swagger UI, without using FromQuery?

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.
    }
}

问题是,当为此控制器生成 Swagger 文档时,会为 DoTheThing 列出以下输入:

foo: int
Thing: string
AnotherThing: DateTime

请注意最后两个输入是如何以大写字母开头的,因为这是它们在模型中的定义方式。 我希望它们以小写字母开头,以便与传递给控制器​​方法的非复杂参数保持一致(请记住,ASP.NET 模型绑定不关心大小写)。

执行此操作的简单方法是在模型上以小写字母开头命名这些属性,或者在它们上应用 FromQuery and/or FromBody 属性。我不想做这两件事,因为前者很讨厌,而后者正在将行为应用于属性,当我需要根据具体情况应用该行为时。

理想情况下,我希望能够编写如下内容(目前不起作用,因为 Swashbuckle 似乎没有 know/care 关于 DisplayNameDisplay属性):

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

但是,如果任何解决方案允许我 "rename" 模型属性而不更改它们的名称,我会很高兴。

我看过 Swashbuckle.AspNetCore.Annotations,但它似乎没有提供此功能。

您可以使用 Asp.Net 核心中的 IDocumentFilter 来实现,我不确定这是否会在正常 Asp.Net 中工作,但解决方案必须相似。

DocumentFilter 迭代所有参数并降低第一个字母。

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
}

然后在swagger配置中注册die DocumentFilter:

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

我根据描述枚举参数的示例调整了这段代码,但同样的想法也适用于重命名。

要强制所有参数都为小写,请使用名称明显但文档不足的 DescribeAllParametersInCamelCase 方法:

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

(这最终成为一个 XY 问题,因为我想要的是一种强制所有参数都被描述为小写的方法,但找不到方法来做到这一点,所以我要求一个通用的修改参数名称的方法。)