如何定义 Swagger UI 参数的默认值?



我已将Swagger/Swashbuckle集成到.NET Core 2.2 API项目中。 一切都很好,我所要求的纯粹是为了方便。 请考虑以下 API 方法:

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

当我点击/swagger/index.html 并想试用此 API 时,我始终必须输入 StreetAddress 和 Zip 值。

有没有办法为街道地址和邮政编码提供默认值? 这个答案建议放置 [DefaultValue("value here")] 属性SomeRequest类的每个属性。 它可能适用于常规的.NET,但不适用于.NET Core。

是否可以为 Swagger UI 的参数提供默认值?

若要为 .NET Core 中的 Swagger UI 定义参数的默认值,以下文章为 Model 类中的 DefaultValue 属性定义自定义架构筛选器。下面显示的代码取自本文,纯粹是为了通知有此问题或遇到类似问题的其他任何人:

在模型中装饰所需的属性:

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

主过滤器:

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);
}
}
}

最后将其注册到您的 Swagger 选项(启动中.cs):

services.AddSwaggerGen(c => {
// ...
c.SchemaFilter<SchemaFilter>();
});

最初的功劳归于Rahul Sharma,但如果有人对.NET Core 3.0+感兴趣,Swashbuckle v5.0.0-rc4使SchemaFilter的定义变得更加简单。也许有一种方法可以使用新属性或类似的东西添加示例值,但我还没有找到这样的方法。

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

Swashbuckle.AspNetCore 5.6.3只需要DefaultValueAttribute

Swashbuckle.AspNetCore 5.6.3 只需要像这样System.ComponentModel.DefaultValueAttribute

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

对于引用类型属性(如datetime类型),不能使用该System.ComponentModelDefaultValueAttribute,因为它不支持引用类型初始化。 对于这种情况,我创建了一个自定义默认值属性,该属性获取字符串值并将其转换为基元类型。然后我定义了一个架构过滤器,将值设置为默认的memberInfo架构:

  1. 默认值属性
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. 将过滤器添加到 Swagger
services.AddSwaggerGen(c =>
{
c.SchemaFilter<DefaultValuesSwaggerExtensions>();
});
  1. 将属性添加到属性
[DTOs.Common.DefaultValue(Microsoft.OpenApi.Any.PrimitiveType.DateTime, -1)]
public DateTime FromDate { get; set; } = DateTime.Now.AddYears(-1);

对于值类型,您可以使用如下所示System.ComponentModel.DefaultValueAttribute

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

对于基元类型属性(如datetime类型),不能在System.ComponentModelDefaultValueAttribute中添加默认值,因为属性不支持引用类型初始化。 对于这种情况,我创建了一个自定义默认值属性,该属性获取字符串值并将其转换为基元类型。然后我定义了一个架构过滤器,将值设置为默认的memberInfo架构:

  1. 默认值属性
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. 将过滤器添加到 Swagger
services.AddSwaggerGen(c =>
{
c.SchemaFilter<DefaultValuesSwaggerExtensions>();
});
  1. 使用属性的属性
[DTOs.Common.DefaultValue(Microsoft.OpenApi.Any.PrimitiveType.DateTime, -1)]
public DateTime FromDate { get; set; } = DateTime.Now.AddYears(-1);

这是对我有用的东西

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

最新更新