Example #1
0
        private static void AddQueryOperation(NSwag.OpenApiOperation operation, CommandEndpointRegistration registration, bool patternParametersOnly = false)
        {
            foreach (var property in registration.RequestType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                // translate commandType properties to many OpenApiParameters
                if (!property.CanWrite || !property.CanRead)
                {
                    continue;
                }

                var type = JsonObjectType.String;
                if (property.PropertyType == typeof(int) || property.PropertyType == typeof(short))
                {
                    type = JsonObjectType.Integer;
                }
                else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(float) || property.PropertyType == typeof(long))
                {
                    type = JsonObjectType.Number;
                }
                else if (property.PropertyType == typeof(bool))
                {
                    type = JsonObjectType.Boolean;
                }
                else if (property.PropertyType == typeof(object))
                {
                    type = JsonObjectType.Object; // TODO: does not work for child objects
                }

                if (!patternParametersOnly)
                {
                    // always add parameter
                    operation.Parameters.Add(new OpenApiParameter
                    {
                        //Description = "request model", // TODO: define a description per param (dictionary) and use it here
                        Kind = registration.Pattern.Contains($"{{{property.Name}", StringComparison.OrdinalIgnoreCase)
                            ? OpenApiParameterKind.Path
                            : OpenApiParameterKind.Query, // query routes are not really supported!
                        Name = property.Name.Camelize(),
                        Type = type,
                    });
                }
                else
                {
                    // only add parameter if it appears in the route pattern
                    if (registration.Pattern.Contains($"{{{property.Name}", StringComparison.OrdinalIgnoreCase))
                    {
                        operation.Parameters.Add(new OpenApiParameter
                        {
                            //Description = "request model", // TODO: define a description per param (dictionary) and use it here
                            Kind = OpenApiParameterKind.Path,
                            Name = property.Name.Camelize(),
                            Type = type,
                        });
                    }
                }
            }
        }
Example #2
0
 private static void AddBodyOperation(NSwag.OpenApiOperation operation, CommandEndpointRegistration registration, DocumentProcessorContext context)
 {
     operation.Parameters.Add(new OpenApiParameter
     {
         Description = registration.OpenApi?.RequestBodyDescription, //registration.RequestType.PrettyName(), //"request model",
         Kind        = OpenApiParameterKind.Body,
         Name        = registration.RequestType.PrettyName(),        //"model",
         Type        = JsonObjectType.Object,
         Schema      = EnsureSchema(registration, context),
         //Example = registration.CommandType != null ? Factory.Create(registration.CommandType) : null //new Commands.Domain.EchoCommand() { Message = "test"},
     });
 }
Example #3
0
 private static void AddResponseHeaders(NSwag.OpenApiOperation operation, CommandEndpointRegistration registration)
 {
     foreach (var response in operation.Responses)
     {
         if (registration.RequestType.GetInterfaces().Contains(typeof(ICommand)))
         {
             response.Value.Headers.Add("X-CommandId", new OpenApiHeader {
                 Type = JsonObjectType.String
             });
         }
         else if (registration.RequestType.GetInterfaces().Contains(typeof(IQuery)))
         {
             response.Value.Headers.Add("X-QueryId", new OpenApiHeader {
                 Type = JsonObjectType.String
             });
         }
     }
 }
Example #4
0
 private static void AddOperationParameters(NSwag.OpenApiOperation operation, string method, CommandEndpointRegistration registration, DocumentProcessorContext context)
 {
     if (registration.RequestType != null)
     {
         if (method.SafeEquals("get") || method.SafeEquals("delete"))
         {
             AddQueryOperation(operation, registration);
         }
         else if (method.SafeEquals("post") || method.SafeEquals("put") || method.SafeEquals("patch") || method.SafeEquals(string.Empty))
         {
             AddQueryOperation(operation, registration, true);
             AddBodyOperation(operation, registration, context);
         }
         else
         {
             // TODO: ignore for now, or throw? +log
         }
     }
 }
Example #5
0
        private static void AddPathItem(IDictionary <string, OpenApiPathItem> items, IEnumerable <CommandEndpointRegistration> registrations, DocumentProcessorContext context)
        {
            var item = new OpenApiPathItem();

            foreach (var registration in registrations)
            {
                var method    = registration.Method.ToString().ToLower();
                var operation = new NSwag.OpenApiOperation
                {
                    Description = registration.OpenApi.Description,
                    Summary     = registration.OpenApi.Summary,
                    OperationId = registration.RequestType.Name, //GetStringSha256Hash($"{method} {registration.Pattern}"),
                    Tags        = new[] { !registration.OpenApi.GroupName.IsNullOrEmpty() ? $"{registration.OpenApi.GroupPrefix} {registration.OpenApi.GroupName}".Trim() : registration.OpenApi.GroupPrefix }.ToList(),
                    Produces = !registration.OpenApi.Produces.IsNullOrEmpty() ? registration.OpenApi.Produces.Split(';').Distinct().ToList() : new[] { "application/json" }.ToList()
                    //RequestBody = new OpenApiRequestBody{}
                };

                item.Add(method, operation);

                var hasResponseModel = registration.Response?.IgnoreResponseBody == false && registration.ResponseType != typeof(Unit) && registration.ResponseType?.Name.SafeEquals("object") == false;
                var description      = hasResponseModel ? registration.ResponseType.PrettyName() : string.Empty;
                var schema           = context.SchemaGenerator.Generate(registration.ResponseType, context.SchemaResolver);
                var schemaKey        = registration.ResponseType.PrettyName();

                // reuse some previously generated schemas, so schema $refs are avoided
                if (ResponseSchemas.ContainsKey(schemaKey))
                {
                    schema = ResponseSchemas[schemaKey];
                }
                else
                {
                    ResponseSchemas.Add(schemaKey, schema);
                }

                if (registration.Response == null)
                {
                    operation.Responses.Add(((int)HttpStatusCode.OK).ToString(), new OpenApiResponse
                    {
                        Description = description,
                        Schema      = hasResponseModel ? schema : null,
                        //Examples = hasResponseModel ? Factory.Create(registration.ResponseType) : null // header?
                    });
                }
                else
                {
                    operation.Responses.Add(((int)registration.Response.OnSuccessStatusCode).ToString(), new OpenApiResponse
                    {
                        Description = description,
                        Schema      = hasResponseModel ? schema : null,
                        //Examples = hasResponseModel ? Factory.Create(registration.ResponseType) : null // header?
                    });
                }

                operation.Responses.Add(((int)HttpStatusCode.BadRequest).ToString(), new OpenApiResponse
                {
                    Description = nameof(ProblemDetails),
                    Schema      = ResponseSchemas[nameof(ProblemDetails)]
                });
                operation.Responses.Add(((int)HttpStatusCode.InternalServerError).ToString(), new OpenApiResponse
                {
                    Description = nameof(ProblemDetails),
                    Schema      = ResponseSchemas[nameof(ProblemDetails)]
                });

                AddResponseHeaders(operation, registration);
                AddOperationParameters(operation, method, registration, context);
            }

            if (item.Any() && !items.ContainsKey(registrations.First().Pattern))
            {
                items?.Add(registrations.First().Pattern, item);
            }
        }