【发布时间】:2020-03-10 20:27:10
【问题描述】:
我有一个 swashbuckle swaggergen UI 输出,如下所示: [![提出请求][1]][1]
而且(出于某种原因),我不想使用典型的验证属性,而是在请求正文中进行验证。我的容器名称是一个 Azure Blob 存储容器,所以它必须是 3-63 个字符并且匹配一个简单的正则表达式(没有大写字母,基本上是字母数字)。
我想修改 UI 以显示这些要求...所以,我编写了 OperationFilter 和 Attribute。我假设我想修改 SwaggerParameters,在那里我注意到一个方便的模式,其中包含“MinLength”、“MaxLength”和“Pattern”等参数——换句话说,正是我想要在我的 UI 上显示的内容。所以我修改了那个。这是输出:
"put": {
"tags": [
"Values"
],
"summary": "API Operation – Create & Update\r\n::\r\nCreates a new content file entry in the containername provided.",
"description": "If the container name has the word public in it, then the container\r\nshall be public otherwise the container, identified by the\r\ncontainername, shall be private. If the file, identified by the\r\nfilename parameter on the URI, already exists then the existing blob\r\nentry will be overwritten with the new fileData uploaded.",
"operationId": "Put",
"parameters": [
{
"name": "containername",
"in": "path",
"description": "The container the file resides in.",
"required": true,
"schema": {
"maxLength": 63,
"minLength": 3,
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
"type": "string"
}
},
{
"name": "fileName",
"in": "path",
"description": "The name of the file uploaded. This shall become the block blob Id.",
"required": true,
"schema": {
"maxLength": 75,
"minLength": 1,
"pattern": "\\S",
"type": "string"
}
}
],
问题是,用户界面看起来一样。我应该修改什么来渲染这些值?
执行此操作的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using static Foo.SwaggerParameterDescriptions;
namespace Foo
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerPathParameterDescriptions : Attribute
{
public enum Description
{
Default,
MinLength,
MaxLength,
Pattern
}
public string ParameterName { get; set; }
public Dictionary<Description, dynamic> Settings { get; set; }
public SwaggerPathParameterDescriptions(string parameterName, string json)
{
Dictionary<string, dynamic> dict = JsonSerializer
.Deserialize<Dictionary<string, dynamic>>(json);
Dictionary<Description, dynamic> settings = dict.Entries()
.ToDictionary(entry => (Description)Enum.Parse(typeof(Description), (string)entry.Key),
entry => entry.Value);
ParameterName = parameterName;
Settings = settings;
}
public IEnumerable<SwaggerParameterSchemaDescription> GetSwaggerParameters()
{
return Settings.Keys.Select(key =>
new SwaggerParameterSchemaDescription { ParameterName = key, Value = Settings[key] });
}
}
public class SwaggerParameterSchemaDescription
{
public Description ParameterName { get; set; }
public dynamic Value { get; set; }
public void ApplyTo(OpenApiParameter param)
{
string representation = $"{Value}";
switch (ParameterName)
{
case Description.Default:
param.Schema.Default = new OpenApiString(representation); // Path Parameters must be strings!
break;
case Description.MinLength:
param.Schema.MinLength = Int32.Parse(representation);
break;
case Description.MaxLength:
param.Schema.MaxLength = Int32.Parse(representation);
break;
case Description.Pattern:
param.Schema.Pattern = representation;
break;
default:
throw new InvalidOperationException();
}
}
}
public class AddSettings : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
foreach (var param in operation.Parameters)
{
var actionParam = context.ApiDescription.ActionDescriptor.Parameters.First(p => p.Name == param.Name);
if (actionParam != null)
{
context.MethodInfo
.GetCustomAttributes(true)
.OfType<SwaggerPathParameterDescriptions>()
.Where(p => p.ParameterName == param.Name)
.ToList()
.ForEach(customAttribute =>
{
foreach (SwaggerParameterSchemaDescription description in customAttribute.GetSwaggerParameters())
{
description.ApplyTo(param);
}
});
}
}
}
}
}
在启动中:
services.AddSwaggerGen(c => {
c.OperationFilter<AddSettings>();
然后使用like:
[HttpPut("{containername}/contentfiles/{fileName}")]
[SwaggerPathParameterDescriptions("containername", "{\"MinLength\":3,\"MaxLength\":63,\"Pattern\":\"^[a-z0-9]+(-[a-z0-9]+)*$\"}")]
[SwaggerPathParameterDescriptions("fileName", "{\"MinLength\":1,\"MaxLength\":75,\"Pattern\":\"\\\\S\"}")]
[SwaggerResponseHeader(StatusCodes.Status201Created, "Location", "string", "Location of the newly created resource")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)]
public ActionResult Put(string containername, string fileName, IFormFile fileData)
我的问题是它没有渲染。 :( 我还有更多工作要做?还是我修改了错误的值?
【问题讨论】:
-
由于某种原因它不允许我发布我的图片..当我拖放它然后发布时,它说“身体不能包含我的点堆栈点 imgur dot com slash nTFyg.png”图像在那里可见
-
你的API定义是
swagger: "2.0"还是openapi: 3.0.0? -
"openapi": "3.0.1", ... 它从 Swashbuckle.AspNetCore.SwaggerGen 生成
-
我认为这被否决真是太搞笑了......这里最活跃的招摇的贡献者之一跳出来回答我的问题
标签: asp.net-core swagger swagger-ui openapi swashbuckle