代码之家  ›  专栏  ›  技术社区  ›  Jude

如何在ProducesResponseType Swagger上返回泛型类型?

  •  2
  • Jude  · 技术社区  · 8 年前

    在下面的代码中,您将在 ,但我无法使其工作,因为它不是特定类型:

     public class ApiController<T> : ApiBaseController where T : class, IDocument
      {    
        protected IDataService<T> data = null;
    
        [HttpGet("{id}")]
        **[ProducesResponseType(typeof(T), 201)]**
        [ProducesResponseType(typeof(void), 500)]         
        public async Task<IActionResult> Get(string id)
        {
            var result = await data.Get(id);
    
            return Ok(result);
        }
     }
    

    有什么建议吗?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Tseng    8 年前

    仔细观察后,似乎可以(更容易)使用操作过滤器。

    这方面的一些东西应该可以工作(未经测试,只是确保没有编译错误)。

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

    它做什么? IOperationFilter ControllerActionDescriptor 如果是,请检查控制器类型。

    如果您愿意,可以将其缩小到一种特定类型。我刚刚获取了从另一个类继承的每个控制器,它的基类型是泛型的 一个 通用参数。

    最后,它检查它是否是“Get”操作(post、put、delete通常不返回模型,只返回状态代码/错误响应),然后检查类型是否已经在Swagger/OpenAPI模式定义中。如果模型在那里,请阅读它的模式并在响应中引用它。

    如果模型未在模式注册表中注册,则会变得更复杂。您需要使用反射并构建模式文件,将其添加到存储库(在 context.SchemaRegistry.GetOrRegister(typeParam) 打电话),然后像上面那样引用它。

    您可以获得有关OpenAPI 2.0规范的更多信息。