經過仔細觀察,似乎可以(並且更容易)使用操作過濾器。
沿着這個線應該工作(未經測試,只是確保它沒有編譯錯誤)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Controllers;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MyCompany.Common.Web.Swagger.OperationFilters
{
public class GenericOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor controllerDescriptor)
{
var baseType = controllerDescriptor.ControllerTypeInfo.BaseType?.GetTypeInfo();
// Get type and see if its a generic controller with a single type parameter
if (baseType == null || (!baseType.IsGenericType && baseType.GenericTypeParameters.Length == 1))
return;
if (context.ApiDescription.HttpMethod == "GET" && !operation.Responses.ContainsKey("200"))
{
var typeParam = baseType.GenericTypeParameters[0];
// Get the schema of the generic type. In case it's not there, you will have to create a schema for that model
// yourself, because Swagger may not have added it, because the type was not declared on any of the models
string typeParamFriendlyId = typeParam.FriendlyId();
if (!context.SchemaRegistry.Definitions.TryGetValue(typeParamFriendlyId, out Schema typeParamSchema))
{
// Schema doesn't exist, you need to create it yourself, i.e. add properties for each property of your model.
// See OpenAPI/Swagger Specifications
typeParamSchema = context.SchemaRegistry.GetOrRegister(typeParam);
// add properties here, without it you won't have a model description for this type
}
// for any get operation for which no 200 response exist yet in the document
operation.Responses.Add("200", new Response
{
Description = "Success",
Schema = new Schema { Ref = typeParamFriendlyId }
});
}
}
}
}
}
它能做什麼?每個操作(Get,Post,Put等)都會調用IOperationFilter
。在它裏面,你檢查它是否是ControllerActionDescriptor
,如果是,請檢查控制器類型。
如果您願意,您可以縮小爲一種特定類型。我剛剛採取了從另一個類繼承的每個控制器,它的基類型與通用參數通用。然後檢查它是否爲「Get」操作(post,put,delete通常不返回模型,只是狀態碼/錯誤響應),然後檢查該類型是否已經在Swagger/OpenAPI中模式定義。如果模型在那裏,請閱讀它的模式並在響應中引用它。
如果模型未在模式註冊表中註冊,則會變得更加複雜。您需要使用反射並構建模式文件,將其添加到存儲庫(在調用context.SchemaRegistry.GetOrRegister(typeParam)
期間已發生),然後按照上面的方法引用它。
當模型沒有用作任何其他控制器中的響應或動作參數時,會發生這種情況。
您可以獲得關於OpenAPI 2.0規範的更多信息。
您無法通過屬性。但是你可以編寫你自己的'ISchemaFilter'或者'IDocumentFilter'來修改打開的api文件,在它被序列化爲json之前 – Tseng
@Tseng你有沒有這方面的示例? – Jude