2016-03-23 21 views
7

スワッガーのドキュメントで設定可能な方法でSwashBuckleを使用してWebAPIルートを表示/非表示する方法を探しています。 [ApiExplorerSettings(IgnoreApi = true)]を追加すると実際には経路が隠されますが、変更したいときはいつでも再コンパイルする必要があります。SwashBuckleでIOperationFilterを使用してルートを削除する

私が定義したカスタム属性で作業するためにIOperationFilterを作成しました。そうすれば、私は[SwaggerTag("MobileOnly")]でルートを飾ることができ、ルートが表示されるべきかどうかをweb.configなどで確認できます。属性は、次のように定義されます

public class SwaggerTagAttribute : Attribute 
{ 
    public string[] Tags { get; private set; } 

    public SwaggerTagAttribute(params string[] tags) 
    { 
     this.Tags = tags; 
    } 
} 

属性を検出IOperationFilterが定義されていると、パスを削除しIDocumentFilterがここで定義されています

public class RemoveTaggedOperationsFilter : IOperationFilter, IDocumentFilter 
{ 
    private List<string> TagsToHide; 

    public RemoveTaggedOperationsFilter() 
    { 
     TagsToHide = ConfigurationManager.AppSettings["TagsToHide"].Split(',').ToList(); 
    } 

    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) 
    { 
     var tags = apiDescription.ActionDescriptor 
      .GetCustomAttributes<SwaggerTagAttribute>() 
      .Select(t => t.Tags) 
      .FirstOrDefault(); 

     if (tags != null && TagsToHide.Intersect(tags).Any()) 
     { 
      operation.tags = new List<string> {"Remove Me "}; 
     } 
    } 

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) 
    { 
     foreach (var value in swaggerDoc.paths.Values) 
     { 
      if (value.post != null && value.post.tags.Contains("Remove Me")) 
       value.post = null; 

      if (value.get != null && value.get.tags.Contains("Remove Me")) 
       value.get = null; 

      if (value.put != null && value.put.tags.Contains("Remove Me")) 
       value.put = null; 

      if (value.delete != null && value.delete.tags.Contains("Remove Me")) 
       value.delete = null; 
     } 
    } 
} 

、そのように登録:

GlobalConfiguration.Configuration 
      .EnableSwagger(c => 
       { 
        c.OperationFilter<RemoveTaggedOperationsFilter>(); 
        c.DocumentFilter<RemoveTaggedOperationsFilter>(); 
       }); 

これは、以前にアクセスしたときに削除するタグを付けるのは非効率的で、ハッキーです。 IOperationFilter.Applyのルートを削除して、IDocumentFilterを待ってスキャンする方法はありますか?

答えて

3

誰かが以前に回答を投稿していて、チャンスがあったらコードを投稿すると言っていました。彼らは何らかの理由で答えを削除しましたが、より良い解決策になりました。

後ではなく、あなただけのカスタム属性を検索しIDocumentFilterを使用して、一挙にそれを削除することができ、ルートを削除するには、ルートにタグを付けるためにIOperationFilterを使用して、IDocumentFilter。以下のコードは次のとおりです。

public class HideTaggedOperationsFilter : IDocumentFilter 
{ 
    private List<string> TagsToHide; 

    public HideTaggedOperationsFilter() 
    { 
     TagsToHide = ConfigurationManager.AppSettings["TagsToHide"].Split(',').ToList(); 
    } 

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) 
    { 
     if (_tagsToHide == null) return; 

     foreach (var apiDescription in apiExplorer.ApiDescriptions) 
     { 
      var tags = apiDescription.ActionDescriptor 
       .GetCustomAttributes<SwaggerTagAttribute>() 
       .Select(t => t.Tags) 
       .FirstOrDefault(); 

      if (tags == null || !_tagsToHide.Intersect(tags).Any()) 
       continue; 

      var route = "/" + apiDescription.Route.RouteTemplate.TrimEnd('/'); 
      swaggerDoc.paths.Remove(route); 
     } 
    } 
} 

public class SwaggerTagAttribute : Attribute 
{ 
    public string[] Tags { get; } 

    public SwaggerTagAttribute(params string[] tags) 
    { 
     this.Tags = tags; 
    } 
} 

IDocumentFilterを登録します。

GlobalConfiguration.Configuration.EnableSwagger(c => 
{ 
    ... 
    c.DocumentFilter<HideTaggedOperationsFilter>(); 
}); 

それからちょうどそのようにルートを飾る:

[SwaggerTag("MobileOnly")] 
public IHttpActionResult SendTest(Guid userId) 
{ 
    return OK(); 
} 

Edit: SwashBuckleためのGitHubのページにいくつかの問題の記事があります。 swaggerDoc.pathの各HTTP動詞をヌルに設定することをお勧めします。Apply。 AutoRestのような多くの自動コードジェネレータを壊すことがわかったので、単にパス全体を削除するだけです。

+0

異なる動詞で同じルートを使用していて、いくつかの動詞だけを無効にしたい場合、この方法は機能しません。つまり、GET/transcationsとPOST/transactionsを持っていれば、カスタム属性で1つのアクションメソッドしか装飾されていないと、両方とも削除されます。 httpメソッドも考慮する必要があります。 –

+0

@ParaJacoそれは大きなポイントです。おそらくHTTP動詞を考慮に入れて拡張するのは難しいことではないでしょう。 – LukeP

+0

コントローラー全体を飾ることができますか? – Rbacarin

関連する問題