2017-10-18 13 views
0

、あなたがProducesResponseTypeにT型(ジェネリック)を参照してくださいよ、私はそれが特定のタイプではないので、それが動作させることができないよ:ProducesResponseType Swaggerでジェネリック型を返すには?以下のコードで

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

任意の提案ですか?

+0

属性を使用することはできません。しかし、自分自身の 'ISchemaFilter'や' IDocumentFilter'を書くことで、公開されているAPIドキュメントをjsonにシリアル化する直前に変更することができます – Tseng

+0

@Tsengこのサンプルはありますか? – Jude

答えて

1

近い見方をした後、操作フィルタを使用すると簡単にできます。

これの行に沿って何かが動作するはずです(テストされていない、コンパイルエラーがないことを確認しただけです)。

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は、操作(Get、Post、Putなど)ごとに呼び出されます。その中にControllerActionDescriptorかどうかをチェックし、そうならコントローラのタイプをチェックします。

必要に応じて、特定の種類に絞り込むことができます。私はちょうど別のクラスから継承するすべてのコントローラーを取ってきました。ベースタイプはの1つのジェネリックパラメーターで一般的です。

最後に、「取得」操作(ポスト、プット、削除は通常モデルを返さず、ステータスコード/エラー応答のみ)をチェックし、タイプが既にSwagger/OpenAPIにあるかどうかを確認しますスキーマ定義。モデルがあれば、そのスキーマを読んでレスポンスで参照してください。

モデルがスキーマレジストリに登録されていない場合、モデルはより複雑になります。リフレクションを使用してスキーマファイルをビルドし、それをリポジトリに追加してください(既にcontext.SchemaRegistry.GetOrRegister(typeParam)呼び出し中に発生しています)。

これは、モデルが他のコントローラの応答パラメータまたはアクションパラメータとして使用されていない場合に発生します。

OpenAPI 2.0仕様について詳しくは、こちらをご覧ください。

関連する問題