Browse Source

Swagger update.

pull/363/head
Sebastian Stehle 7 years ago
parent
commit
e50b931767
  1. 2
      src/Squidex/Areas/Api/Config/Swagger/FixProcessor.cs
  2. 29
      src/Squidex/Areas/Api/Config/Swagger/SecurityProcessor.cs
  3. 3
      src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs
  4. 39
      src/Squidex/Areas/Api/Config/Swagger/XmlResponseTypesProcessor.cs
  5. 84
      src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaSwaggerGenerator.cs
  6. 28
      src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasSwaggerGenerator.cs
  7. 4
      src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs
  8. 10
      src/Squidex/Pipeline/Swagger/NSwagHelper.cs

2
src/Squidex/Areas/Api/Config/Swagger/FixProcessor.cs

@ -13,7 +13,7 @@ using Squidex.Infrastructure.Tasks;
namespace Squidex.Areas.Api.Config.Swagger namespace Squidex.Areas.Api.Config.Swagger
{ {
public class FixProcessor : IOperationProcessor public sealed class FixProcessor : IOperationProcessor
{ {
private static readonly JsonSchema4 StringSchema = new JsonSchema4 { Type = JsonObjectType.String }; private static readonly JsonSchema4 StringSchema = new JsonSchema4 { Type = JsonObjectType.String };

29
src/Squidex/Areas/Api/Config/Swagger/SecurityProcessor.cs

@ -15,7 +15,7 @@ using Squidex.Web;
namespace Squidex.Areas.Api.Config.Swagger namespace Squidex.Areas.Api.Config.Swagger
{ {
public class SecurityProcessor : SecurityDefinitionAppender public sealed class SecurityProcessor : SecurityDefinitionAppender
{ {
public SecurityProcessor(IOptions<UrlsOptions> urlOptions) public SecurityProcessor(IOptions<UrlsOptions> urlOptions)
: base(Constants.SecurityDefinition, Enumerable.Empty<string>(), CreateOAuthSchema(urlOptions.Value)) : base(Constants.SecurityDefinition, Enumerable.Empty<string>(), CreateOAuthSchema(urlOptions.Value))
@ -24,26 +24,33 @@ namespace Squidex.Areas.Api.Config.Swagger
private static SwaggerSecurityScheme CreateOAuthSchema(UrlsOptions urlOptions) private static SwaggerSecurityScheme CreateOAuthSchema(UrlsOptions urlOptions)
{ {
var securityScheme = new SwaggerSecurityScheme(); var security = new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.OAuth2
};
var tokenUrl = urlOptions.BuildUrl($"{Constants.IdentityServerPrefix}/connect/token", false); var tokenUrl = urlOptions.BuildUrl($"{Constants.IdentityServerPrefix}/connect/token", false);
securityScheme.TokenUrl = tokenUrl; security.TokenUrl = tokenUrl;
var securityDocs = NSwagHelper.LoadDocs("security"); SetupDescription(security, tokenUrl);
var securityText = securityDocs.Replace("<TOKEN_URL>", tokenUrl);
securityScheme.Description = securityText; security.Flow = SwaggerOAuth2Flow.Application;
securityScheme.Type = SwaggerSecuritySchemeType.OAuth2;
securityScheme.Flow = SwaggerOAuth2Flow.Application;
securityScheme.Scopes = new Dictionary<string, string> security.Scopes = new Dictionary<string, string>
{ {
[Constants.ApiScope] = "Read and write access to the API" [Constants.ApiScope] = "Read and write access to the API"
}; };
return securityScheme; return security;
}
private static void SetupDescription(SwaggerSecurityScheme securityScheme, string tokenUrl)
{
var securityDocs = NSwagHelper.LoadDocs("security");
var securityText = securityDocs.Replace("<TOKEN_URL>", tokenUrl);
securityScheme.Description = securityText;
} }
} }
} }

3
src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs

@ -22,6 +22,9 @@ namespace Squidex.Areas.Api.Config.Swagger
{ {
public static void AddMySwaggerSettings(this IServiceCollection services) public static void AddMySwaggerSettings(this IServiceCollection services)
{ {
services.AddSingletonAs<ErrorDtoProcessor>()
.As<IDocumentProcessor>();
services.AddSingletonAs<RuleActionProcessor>() services.AddSingletonAs<RuleActionProcessor>()
.As<IDocumentProcessor>(); .As<IDocumentProcessor>();

39
src/Squidex/Areas/Api/Config/Swagger/XmlResponseTypesProcessor.cs

@ -6,16 +6,12 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using NJsonSchema.Infrastructure; using NJsonSchema.Infrastructure;
using NSwag; using NSwag;
using NSwag.SwaggerGeneration.Processors; using NSwag.SwaggerGeneration.Processors;
using NSwag.SwaggerGeneration.Processors.Contexts; using NSwag.SwaggerGeneration.Processors.Contexts;
using Squidex.Pipeline.Swagger;
#pragma warning disable RECS0033 // Convert 'if' to '||' expression
namespace Squidex.Areas.Api.Config.Swagger namespace Squidex.Areas.Api.Config.Swagger
{ {
@ -53,42 +49,7 @@ namespace Squidex.Areas.Api.Config.Swagger
} }
} }
await AddInternalErrorResponseAsync(context, operation);
CleanupResponses(operation);
return true; return true;
} }
private static async Task AddInternalErrorResponseAsync(OperationProcessorContext context, SwaggerOperation operation)
{
var errorSchema = await context.SchemaGenerator.GetErrorDtoSchemaAsync(context.SchemaResolver);
if (!operation.Responses.ContainsKey("500"))
{
operation.AddResponse("500", "Operation failed", errorSchema);
}
foreach (var (code, response) in operation.Responses)
{
if (code != "404" && code.StartsWith("4", StringComparison.OrdinalIgnoreCase) && response.Schema == null)
{
response.Schema = errorSchema;
}
}
}
private static void CleanupResponses(SwaggerOperation operation)
{
foreach (var (code, response) in operation.Responses.ToList())
{
if (string.IsNullOrWhiteSpace(response.Description) ||
response.Description?.Contains("=&gt;") == true ||
response.Description?.Contains("=>") == true)
{
operation.Responses.Remove(code);
}
}
}
} }
} }

84
src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaSwaggerGenerator.cs

@ -32,6 +32,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private readonly string schemaName; private readonly string schemaName;
private readonly string schemaType; private readonly string schemaType;
private readonly string appPath; private readonly string appPath;
private readonly JsonSchema4 statusSchema;
private readonly string appName; private readonly string appName;
static SchemaSwaggerGenerator() static SchemaSwaggerGenerator()
@ -46,6 +47,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
string appPath, string appPath,
Schema schema, Schema schema,
SchemaResolver schemaResolver, SchemaResolver schemaResolver,
JsonSchema4 statusSchema,
PartitionResolver partitionResolver) PartitionResolver partitionResolver)
{ {
this.document = document; this.document = document;
@ -53,6 +55,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
this.appName = appName; this.appName = appName;
this.appPath = appPath; this.appPath = appPath;
this.statusSchema = statusSchema;
schemaPath = schema.Name; schemaPath = schema.Name;
schemaName = schema.DisplayName(); schemaName = schema.DisplayName();
schemaType = schema.TypeName(); schemaType = schema.TypeName();
@ -72,15 +76,13 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
var schemaOperations = new List<SwaggerPathItem> var schemaOperations = new List<SwaggerPathItem>
{ {
GenerateSchemaQueryOperation(), GenerateSchemaGetsOperation(),
GenerateSchemaCreateOperation(),
GenerateSchemaGetOperation(), GenerateSchemaGetOperation(),
GenerateSchemaCreateOperation(),
GenerateSchemaUpdateOperation(), GenerateSchemaUpdateOperation(),
GenerateSchemaPatchOperation(), GenerateSchemaUpdatePatchOperation(),
GenerateSchemaPublishOperation(), GenerateSchemaStatusOperation(),
GenerateSchemaUnpublishOperation(), GenerateSchemaDiscardOperation(),
GenerateSchemaArchiveOperation(),
GenerateSchemaRestoreOperation(),
GenerateSchemaDeleteOperation() GenerateSchemaDeleteOperation()
}; };
@ -90,11 +92,12 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
} }
} }
private SwaggerPathItem GenerateSchemaQueryOperation() private SwaggerPathItem GenerateSchemaGetsOperation()
{ {
return AddOperation(SwaggerOperationMethod.Get, null, $"{appPath}/{schemaPath}", operation => return AddOperation(SwaggerOperationMethod.Get, null, $"{appPath}/{schemaPath}", operation =>
{ {
operation.OperationId = $"Query{schemaType}Contents"; operation.OperationId = $"Query{schemaType}Contents";
operation.Summary = $"Queries {schemaName} contents."; operation.Summary = $"Queries {schemaName} contents.";
operation.Description = SchemaQueryDescription; operation.Description = SchemaQueryDescription;
@ -103,7 +106,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.AddQueryParameter("$skip", JsonObjectType.Number, "Optional number of contents to skip."); operation.AddQueryParameter("$skip", JsonObjectType.Number, "Optional number of contents to skip.");
operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter."); operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter.");
operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search."); operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search.");
operation.AddQueryParameter("orderby", JsonObjectType.String, "Optional OData order definition."); operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition.");
operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition.");
operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema)); operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema));
@ -116,6 +120,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return AddOperation(SwaggerOperationMethod.Get, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => return AddOperation(SwaggerOperationMethod.Get, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation =>
{ {
operation.OperationId = $"Get{schemaType}Content"; operation.OperationId = $"Get{schemaType}Content";
operation.Summary = $"Get a {schemaName} content."; operation.Summary = $"Get a {schemaName} content.";
operation.AddResponse("200", $"{schemaName} content found.", contentSchema); operation.AddResponse("200", $"{schemaName} content found.", contentSchema);
@ -129,12 +134,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return AddOperation(SwaggerOperationMethod.Post, null, $"{appPath}/{schemaPath}", operation => return AddOperation(SwaggerOperationMethod.Post, null, $"{appPath}/{schemaPath}", operation =>
{ {
operation.OperationId = $"Create{schemaType}Content"; operation.OperationId = $"Create{schemaType}Content";
operation.Summary = $"Create a {schemaName} content."; operation.Summary = $"Create a {schemaName} content.";
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content."); operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content.");
operation.AddResponse("201", $"{schemaName} content created.", contentSchema); operation.AddResponse("200", $"{schemaName} content created.", contentSchema);
operation.AddResponse("400", "Content data valid.");
AddSecurity(operation, Permissions.AppContentsCreate); AddSecurity(operation, Permissions.AppContentsCreate);
}); });
@ -145,74 +152,64 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation =>
{ {
operation.OperationId = $"Update{schemaType}Content"; operation.OperationId = $"Update{schemaType}Content";
operation.Summary = $"Update a {schemaName} content."; operation.Summary = $"Update a {schemaName} content.";
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddResponse("200", $"{schemaName} content updated.", dataSchema); operation.AddResponse("200", $"{schemaName} content updated.", contentSchema);
operation.AddResponse("400", "Content data valid.");
AddSecurity(operation, Permissions.AppContentsUpdate); AddSecurity(operation, Permissions.AppContentsUpdate);
}); });
} }
private SwaggerPathItem GenerateSchemaPatchOperation() private SwaggerPathItem GenerateSchemaUpdatePatchOperation()
{ {
return AddOperation(SwaggerOperationMethod.Patch, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation => return AddOperation(SwaggerOperationMethod.Patch, schemaName, $"{appPath}/{schemaPath}/{{id}}", operation =>
{ {
operation.OperationId = $"Path{schemaType}Content"; operation.OperationId = $"Path{schemaType}Content";
operation.Summary = $"Patch a {schemaName} content."; operation.Summary = $"Patch a {schemaName} content.";
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddResponse("200", $"{schemaName} content patched.", dataSchema); operation.AddResponse("200", $"{schemaName} content patched.", contentSchema);
operation.AddResponse("400", "Status change not valid.");
AddSecurity(operation, Permissions.AppContentsUpdate); AddSecurity(operation, Permissions.AppContentsUpdate);
}); });
} }
private SwaggerPathItem GenerateSchemaPublishOperation() private SwaggerPathItem GenerateSchemaStatusOperation()
{ {
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/publish", operation => return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/status", operation =>
{ {
operation.OperationId = $"Publish{schemaType}Content"; operation.OperationId = $"Change{schemaType}ContentStatus";
operation.Summary = $"Publish a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content published."); operation.Summary = $"Change status of {schemaName} content.";
});
}
private SwaggerPathItem GenerateSchemaUnpublishOperation() operation.AddBodyParameter("request", statusSchema, "The request to change content status.");
{
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/unpublish", operation => operation.AddResponse("204", $"{schemaName} content status changed.", contentSchema);
{ operation.AddResponse("400", "Content data valid.");
operation.OperationId = $"Unpublish{schemaType}Content";
operation.Summary = $"Unpublish a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content unpublished."); AddSecurity(operation, Permissions.AppContentsStatus);
}); });
} }
private SwaggerPathItem GenerateSchemaArchiveOperation() private SwaggerPathItem GenerateSchemaDiscardOperation()
{ {
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/archive", operation => return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/discard", operation =>
{ {
operation.OperationId = $"Archive{schemaType}Content"; operation.OperationId = $"Discard{schemaType}Content";
operation.Summary = $"Archive a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content restored."); operation.Summary = $"Discard changes of {schemaName} content.";
AddSecurity(operation, Permissions.AppContentsRead);
});
}
private SwaggerPathItem GenerateSchemaRestoreOperation() operation.AddResponse("400", "No pending draft.");
{ operation.AddResponse("200", $"{schemaName} content status changed.", contentSchema);
return AddOperation(SwaggerOperationMethod.Put, schemaName, $"{appPath}/{schemaPath}/{{id}}/restore", operation =>
{
operation.OperationId = $"Restore{schemaType}Content";
operation.Summary = $"Restore a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content restored."); AddSecurity(operation, Permissions.AppContentsDiscard);
}); });
} }
@ -221,6 +218,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return AddOperation(SwaggerOperationMethod.Delete, schemaName, $"{appPath}/{schemaPath}/{{id}}/", operation => return AddOperation(SwaggerOperationMethod.Delete, schemaName, $"{appPath}/{schemaPath}/{{id}}/", operation =>
{ {
operation.OperationId = $"Delete{schemaType}Content"; operation.OperationId = $"Delete{schemaType}Content";
operation.Summary = $"Delete a {schemaName} content."; operation.Summary = $"Delete a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content deleted."); operation.AddResponse("204", $"{schemaName} content deleted.");

28
src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasSwaggerGenerator.cs

@ -18,6 +18,7 @@ using NSwag.SwaggerGeneration;
using NSwag.SwaggerGeneration.Processors; using NSwag.SwaggerGeneration.Processors;
using NSwag.SwaggerGeneration.Processors.Contexts; using NSwag.SwaggerGeneration.Processors.Contexts;
using Squidex.Areas.Api.Config.Swagger; using Squidex.Areas.Api.Config.Swagger;
using Squidex.Areas.Api.Controllers.Contents.Models;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -32,6 +33,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private readonly SwaggerDocumentSettings settings = new SwaggerDocumentSettings(); private readonly SwaggerDocumentSettings settings = new SwaggerDocumentSettings();
private SwaggerJsonSchemaGenerator schemaGenerator; private SwaggerJsonSchemaGenerator schemaGenerator;
private SwaggerDocument document; private SwaggerDocument document;
private JsonSchema4 statusSchema;
private JsonSchemaResolver schemaResolver; private JsonSchemaResolver schemaResolver;
public SchemasSwaggerGenerator(IOptions<UrlsOptions> urlOptions, IEnumerable<IDocumentProcessor> documentProcessors) public SchemasSwaggerGenerator(IOptions<UrlsOptions> urlOptions, IEnumerable<IDocumentProcessor> documentProcessors)
@ -53,9 +55,9 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
schemaGenerator = new SwaggerJsonSchemaGenerator(settings); schemaGenerator = new SwaggerJsonSchemaGenerator(settings);
schemaResolver = new SwaggerSchemaResolver(document, settings); schemaResolver = new SwaggerSchemaResolver(document, settings);
GenerateSchemasOperations(schemas, app); statusSchema = await GenerateStatusSchemaAsync();
await GenerateDefaultErrorsAsync(); GenerateSchemasOperations(schemas, app);
var context = var context =
new DocumentProcessorContext(document, new DocumentProcessorContext(document,
@ -73,25 +75,23 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return document; return document;
} }
private void GenerateSchemasOperations(IEnumerable<ISchemaEntity> schemas, IAppEntity app) private Task<JsonSchema4> GenerateStatusSchemaAsync()
{ {
var appBasePath = $"/content/{app.Name}"; var errorType = typeof(ChangeStatusDto);
foreach (var schema in schemas.Select(x => x.SchemaDef).Where(x => x.IsPublished)) return schemaGenerator.GenerateWithReferenceAsync<JsonSchema4>(errorType, Enumerable.Empty<Attribute>(), schemaResolver);
{
new SchemaSwaggerGenerator(document, app.Name, appBasePath, schema, AppendSchema, app.PartitionResolver()).GenerateSchemaOperations();
}
} }
private async Task GenerateDefaultErrorsAsync() private void GenerateSchemasOperations(IEnumerable<ISchemaEntity> schemas, IAppEntity app)
{ {
const string errorDescription = "Operation failed with internal server error."; var appBasePath = $"/content/{app.Name}";
var errorDtoSchema = await schemaGenerator.GetErrorDtoSchemaAsync(schemaResolver);
foreach (var operation in document.Paths.Values.SelectMany(x => x.Values)) foreach (var schema in schemas.Select(x => x.SchemaDef).Where(x => x.IsPublished))
{ {
operation.Responses.Add("500", new SwaggerResponse { Description = errorDescription, Schema = errorDtoSchema }); var partition = app.PartitionResolver();
new SchemaSwaggerGenerator(document, app.Name, appBasePath, schema, AppendSchema, statusSchema, partition)
.GenerateSchemaOperations();
} }
} }

4
src/Squidex/Areas/Api/Controllers/Contents/Models/ContentDto.cs

@ -130,14 +130,14 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models
if (controller.HasPermission(Permissions.AppContentsUpdate, app, schema)) if (controller.HasPermission(Permissions.AppContentsUpdate, app, schema))
{ {
AddPatchLink("patch", controller.Url<ContentsController>(x => nameof(x.PatchContent), values));
AddPutLink("update", controller.Url<ContentsController>(x => nameof(x.PutContent), values)); AddPutLink("update", controller.Url<ContentsController>(x => nameof(x.PutContent), values));
if (Status == Status.Published) if (Status == Status.Published)
{ {
AddPutLink("draft/propose", controller.Url<ContentsController>(x => nameof(x.PutContent), values) + "?asDraft=true"); AddPutLink("draft/propose", controller.Url<ContentsController>(x => nameof(x.PutContent), values) + "?asDraft=true");
} }
AddPatchLink("patch", controller.Url<ContentsController>(x => nameof(x.PatchContent), values));
} }
if (controller.HasPermission(Permissions.AppContentsDelete, app, schema)) if (controller.HasPermission(Permissions.AppContentsDelete, app, schema))

10
src/Squidex/Pipeline/Swagger/NSwagHelper.cs

@ -8,11 +8,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using NJsonSchema; using NJsonSchema;
using NJsonSchema.Generation;
using NSwag; using NSwag;
using Squidex.Web; using Squidex.Web;
@ -69,13 +66,6 @@ namespace Squidex.Pipeline.Swagger
return document; return document;
} }
public static async Task<JsonSchema4> GetErrorDtoSchemaAsync(this JsonSchemaGenerator schemaGenerator, JsonSchemaResolver resolver)
{
var errorType = typeof(ErrorDto);
return await schemaGenerator.GenerateWithReferenceAsync<JsonSchema4>(errorType, Enumerable.Empty<Attribute>(), resolver);
}
public static void AddQueryParameter(this SwaggerOperation operation, string name, JsonObjectType type, string description = null) public static void AddQueryParameter(this SwaggerOperation operation, string name, JsonObjectType type, string description = null)
{ {
var parameter = new SwaggerParameter { Type = type, Name = name, Kind = SwaggerParameterKind.Query }; var parameter = new SwaggerParameter { Type = type, Name = name, Kind = SwaggerParameterKind.Query };

Loading…
Cancel
Save