예제 #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,
                        });
                    }
                }
            }
        }
예제 #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"},
     });
 }
예제 #3
0
        private static JsonSchema EnsureSchema(CommandEndpointRegistration registration, DocumentProcessorContext context)
        {
            var schemaKey = registration.RequestType.PrettyName();

            if (RequestSchemas.ContainsKey(schemaKey))
            {
                return(RequestSchemas[schemaKey]);
            }
            else
            {
                var schema = context.SchemaGenerator.Generate(registration.RequestType, context.SchemaResolver);
                RequestSchemas.Add(schemaKey, schema);
                return(schema);
            }
        }
        public CommandEndpointRegistration AddRegistration <TRequest>(string pattern, HttpMethod method)
        {
            this.registrations ??= new List <CommandEndpointRegistration>();
            var registration = new CommandEndpointRegistration
            {
                Name         = typeof(TRequest).Name,
                Pattern      = pattern,
                Method       = method,
                RequestType  = typeof(TRequest),
                ResponseType = typeof(TRequest).GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest <>))?.GetGenericArguments()?[0]
            };

            this.registrations.Add(registration);

            return(registration);
        }
예제 #5
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
             });
         }
     }
 }
예제 #6
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
         }
     }
 }
        private static async Task SendRequest(
            HttpContext context,
            CommandEndpointRegistration registration,
            object requestModel,
            string requestId)
        {
            var mediator = context.RequestServices.GetService <IMediator>();

            try
            {
                var response = await mediator.Send(requestModel, context.RequestAborted).ConfigureAwait(false);

                if (response is Unit) // Unit is the empty mediatr response
                {
                    response = null;
                }

                registration.Response?.InvokeSuccess(requestModel, response, context);
                context.Response.StatusCode = (int)registration.Response.OnSuccessStatusCode;
                context.Response.Headers.Add("Content-Type", registration.OpenApi?.Produces);

                if (response == null && requestModel is IQuery &&
                    !typeof(IEnumerable <>).IsAssignableFrom(registration.ResponseType))
                {
                    // query for single resource with no result > 404
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                }
                else if (response != null && registration.Response?.IgnoreResponseBody == false)
                {
                    await JsonSerializer.SerializeAsync(
                        context.Response.Body,
                        response,
                        response?.GetType() ?? registration.ResponseType,
                        null,
                        context.RequestAborted).ConfigureAwait(false);
                }
            }
            catch (ValidationException ex) // 400
            {
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                context.Response.Headers.Add("Content-Type", "application/problem+json");
                await JsonSerializer.SerializeAsync(
                    context.Response.Body,
                    new ProblemDetails
                {
                    Status   = (int)HttpStatusCode.BadRequest,
                    Title    = "A validation error has occurred while executing the request",
                    Type     = ex.GetType().Name,
                    Detail   = ex.Message,
                    Instance = requestId
                },
                    typeof(ProblemDetails),
                    null,
                    context.RequestAborted).ConfigureAwait(false);
            }
            catch (Exception ex) // 500
            {
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                context.Response.Headers.Add("Content-Type", "application/problem+json");
                await JsonSerializer.SerializeAsync(
                    context.Response.Body,
                    new ProblemDetails
                {
                    Status   = (int)HttpStatusCode.InternalServerError,
                    Title    = "An unhandled error has occurred while processing the request",
                    Type     = ex.GetType().Name,
                    Detail   = ex.Message,
                    Instance = requestId
                },
                    typeof(ProblemDetails),
                    null,
                    context.RequestAborted).ConfigureAwait(false);
            }

            await context.Response.Body.FlushAsync(context.RequestAborted).ConfigureAwait(false);
        }