1
1
using System ;
2
- using System . Collections . Generic ;
3
2
using System . IO ;
4
3
using System . Linq ;
5
4
using System . Reflection ;
@@ -22,9 +21,8 @@ namespace VirtoCommerce.Platform.Web.Swagger
22
21
{
23
22
public static class SwaggerServiceCollectionExtensions
24
23
{
25
- public static string platformDocName { get ; } = "VirtoCommerce.Platform" ;
26
- public static string platformUIDocName { get ; } = "PlatformUI" ;
27
- private static string oauth2SchemeName = "oauth2" ;
24
+ public static string PlatformDocName => "VirtoCommerce.Platform" ;
25
+ public static string PlatformUIDocName => "PlatformUI" ;
28
26
29
27
/// <summary>
30
28
/// Register swagger documents generator
@@ -68,15 +66,15 @@ public static void AddSwagger(this IServiceCollection services, IConfiguration c
68
66
}
69
67
} ;
70
68
71
- c . SwaggerDoc ( platformDocName , platformInfo ) ;
72
- c . SwaggerDoc ( platformUIDocName , platformInfo ) ;
69
+ c . SwaggerDoc ( PlatformDocName , platformInfo ) ;
70
+ c . SwaggerDoc ( PlatformUIDocName , platformInfo ) ;
73
71
74
72
foreach ( var module in modules )
75
73
{
76
74
c . SwaggerDoc ( module . ModuleName , new OpenApiInfo { Title = $ "{ module . Id } ", Version = "v1" } ) ;
77
75
}
78
76
79
- c . TagActionsBy ( api => api . GroupByModuleName ( services ) ) ;
77
+ c . TagActionsBy ( api => [ api . GetModuleName ( provider ) ] ) ;
80
78
c . IgnoreObsoleteActions ( ) ;
81
79
c . DocumentFilter < ExcludeRedundantDepsFilter > ( ) ;
82
80
// This temporary filter removes broken "application/*+json" content-type.
@@ -91,29 +89,24 @@ public static void AddSwagger(this IServiceCollection services, IConfiguration c
91
89
c . SchemaFilter < EnumSchemaFilter > ( ) ;
92
90
c . SchemaFilter < SwaggerIgnoreFilter > ( ) ;
93
91
c . MapType < object > ( ( ) => new OpenApiSchema { Type = "object" } ) ;
94
- c . AddModulesXmlComments ( services ) ;
92
+ c . AddModulesXmlComments ( provider ) ;
95
93
c . CustomOperationIds ( apiDesc =>
96
94
apiDesc . TryGetMethodInfo ( out var methodInfo ) ? $ "{ ( ( ControllerActionDescriptor ) apiDesc . ActionDescriptor ) . ControllerName } _{ methodInfo . Name } " : null ) ;
97
- c . AddSecurityDefinition ( oauth2SchemeName , new OpenApiSecurityScheme
95
+ c . AddSecurityDefinition ( "oauth2" , new OpenApiSecurityScheme
98
96
{
99
97
Type = SecuritySchemeType . OAuth2 ,
100
98
Description = "OAuth2 Resource Owner Password Grant flow" ,
101
- Flows = new OpenApiOAuthFlows ( )
99
+ Flows = new OpenApiOAuthFlows
102
100
{
103
- Password = new OpenApiOAuthFlow ( )
101
+ Password = new OpenApiOAuthFlow
104
102
{
105
- TokenUrl = new Uri ( $ "/connect/token", UriKind . Relative )
103
+ TokenUrl = new Uri ( "/connect/token" , UriKind . Relative )
106
104
}
107
105
} ,
108
106
} ) ;
109
107
110
- c . DocInclusionPredicate ( ( docName , apiDesc ) =>
111
- {
112
- return DocInclusionPredicateCustomStrategy ( modules , docName , apiDesc ) ;
113
- } ) ;
114
-
108
+ c . DocInclusionPredicate ( ( docName , apiDesc ) => DocInclusionPredicateCustomStrategy ( modules , docName , apiDesc ) ) ;
115
109
c . ResolveConflictingActions ( apiDescriptions => apiDescriptions . First ( ) ) ;
116
-
117
110
c . EnableAnnotations ( enableAnnotationsForInheritance : true , enableAnnotationsForPolymorphism : true ) ;
118
111
119
112
if ( useAllOfToExtendReferenceSchemas )
@@ -124,26 +117,25 @@ public static void AddSwagger(this IServiceCollection services, IConfiguration c
124
117
125
118
// Unfortunately, we can't use .CustomSchemaIds, because it changes schema ids for all documents (impossible to change ids depending on document name).
126
119
// But we need this, because PlatformUI document should contain ref schema ids as type.FullName to avoid conflict with same type names in different modules.
127
- // As a solution we use custom swagger generator that catches document name and generates schemaids depending on it
128
- services . AddTransient < ISwaggerProvider , CustomSwaggerGenerator > ( ) ;
120
+ // As a solution we use custom swagger generator that catches document name and generates schema ids depending on it.
121
+ services . AddTransient < IAsyncSwaggerProvider , CustomSwaggerGenerator > ( ) ;
129
122
130
123
//This is important line switches the SwaggerGenerator to use the Newtonsoft contract resolver that uses the globally registered PolymorphJsonContractResolver
131
124
//to propagate up to the resulting OpenAPI schema the derived types instead of base domain types
132
125
services . AddSwaggerGenNewtonsoftSupport ( ) ;
133
-
134
126
}
135
127
136
128
private static bool DocInclusionPredicateCustomStrategy ( ManifestModuleInfo [ ] modules , string docName , ApiDescription apiDesc )
137
129
{
138
- // It's an UI endpoint, return all to correctly build swagger UI page
139
- if ( docName . EqualsInvariant ( platformUIDocName ) )
130
+ // It's a UI endpoint, return all to correctly build swagger UI page
131
+ if ( docName . EqualsInvariant ( PlatformUIDocName ) )
140
132
{
141
133
return true ;
142
134
}
143
135
144
136
// It's a platform endpoint.
145
137
var currentAssembly = ( ( ControllerActionDescriptor ) apiDesc . ActionDescriptor ) . ControllerTypeInfo . Assembly ;
146
- if ( docName . EqualsInvariant ( platformDocName ) && currentAssembly . FullName . StartsWith ( docName ) )
138
+ if ( docName . EqualsInvariant ( PlatformDocName ) && currentAssembly . FullName ? . StartsWith ( docName ) == true )
147
139
{
148
140
return true ;
149
141
}
@@ -168,7 +160,7 @@ public static void UseSwagger(this IApplicationBuilder applicationBuilder)
168
160
applicationBuilder . UseSwagger ( c =>
169
161
{
170
162
c . RouteTemplate = "docs/{documentName}/swagger.{json|yaml}" ;
171
- c . PreSerializeFilters . Add ( ( swagger , httpReq ) =>
163
+ c . PreSerializeFilters . Add ( ( _ , _ ) =>
172
164
{
173
165
} ) ;
174
166
@@ -180,8 +172,8 @@ public static void UseSwagger(this IApplicationBuilder applicationBuilder)
180
172
applicationBuilder . UseSwaggerUI ( c =>
181
173
{
182
174
// Json Format Support
183
- c . SwaggerEndpoint ( $ "./{ platformUIDocName } /swagger.json", platformUIDocName ) ;
184
- c . SwaggerEndpoint ( $ "./{ platformDocName } /swagger.json", platformDocName ) ;
175
+ c . SwaggerEndpoint ( $ "./{ PlatformUIDocName } /swagger.json", PlatformUIDocName ) ;
176
+ c . SwaggerEndpoint ( $ "./{ PlatformDocName } /swagger.json", PlatformDocName ) ;
185
177
186
178
foreach ( var moduleId in modules . OrderBy ( m => m . Id ) . Select ( m => m . Id ) )
187
179
{
@@ -205,17 +197,9 @@ public static void UseSwagger(this IApplicationBuilder applicationBuilder)
205
197
}
206
198
207
199
208
- /// <summary>
209
- /// grouping by Module Names in the ApiDescription
210
- /// with comparing Assemlies
211
- /// </summary>
212
- /// <param name="api"></param>
213
- /// <param name="services"></param>
214
- /// <returns></returns>
215
- private static IList < string > GroupByModuleName ( this ApiDescription api , IServiceCollection services )
200
+ private static string GetModuleName ( this ApiDescription api , ServiceProvider serviceProvider )
216
201
{
217
- var providerSnapshot = services . BuildServiceProvider ( ) ;
218
- var moduleCatalog = providerSnapshot . GetRequiredService < ILocalModuleCatalog > ( ) ;
202
+ var moduleCatalog = serviceProvider . GetRequiredService < ILocalModuleCatalog > ( ) ;
219
203
220
204
// ------
221
205
// Lifted from ApiDescriptionExtensions
@@ -229,20 +213,17 @@ private static IList<string> GroupByModuleName(this ApiDescription api, IService
229
213
// ------
230
214
231
215
var moduleAssembly = actionDescriptor ? . ControllerTypeInfo . Assembly ?? Assembly . GetExecutingAssembly ( ) ;
232
- var groupName = moduleCatalog . Modules . FirstOrDefault ( m => m . ModuleInstance != null && m . Assembly == moduleAssembly ) ;
216
+ var module = moduleCatalog . Modules . FirstOrDefault ( m => m . ModuleInstance != null && m . Assembly == moduleAssembly ) ;
233
217
234
- return new List < string > { groupName != null ? groupName . ModuleName : "Platform" } ;
218
+ return module ? . ModuleName ?? "Platform" ;
235
219
}
236
220
237
221
/// <summary>
238
222
/// Add Comments/Descriptions from XML-files in the ApiDescription
239
223
/// </summary>
240
- /// <param name="options"></param>
241
- /// <param name="services"></param>
242
- private static void AddModulesXmlComments ( this SwaggerGenOptions options , IServiceCollection services )
224
+ private static void AddModulesXmlComments ( this SwaggerGenOptions options , ServiceProvider serviceProvider )
243
225
{
244
- var provider = services . BuildServiceProvider ( ) ;
245
- var localStorageModuleCatalogOptions = provider . GetService < IOptions < LocalStorageModuleCatalogOptions > > ( ) . Value ;
226
+ var localStorageModuleCatalogOptions = serviceProvider . GetService < IOptions < LocalStorageModuleCatalogOptions > > ( ) . Value ;
246
227
247
228
var xmlCommentsDirectoryPaths = new [ ]
248
229
{
0 commit comments