Example #1
0
        /// <inheritdoc />
        public IEnumerable <Frame> GetFrames(Variable operationVariable, List <OperationProperty> properties)
        {
            var contextCreator =
                new ConstructorFrame <ValidationContext>(() => new ValidationContext(null))
            {
                Parameters = { [0] = operationVariable },
            };

            var hasClassLevel    = typeof(IValidatableObject).IsAssignableFrom(operationVariable.VariableType);
            var hasPropertyLevel = properties.Any(p =>
                                                  p.PropertyInfoVariable.Property.GetAttributes <ValidationAttribute>(true).Any());

            if (hasClassLevel || hasPropertyLevel)
            {
                yield return(contextCreator);
            }

            if (hasClassLevel)
            {
                yield return(new ValidatableObjectFrame(contextCreator.Variable, operationVariable));
            }

            if (hasPropertyLevel)
            {
                foreach (var p in properties)
                {
                    var attributes = p.PropertyInfoVariable.Property.GetAttributes <ValidationAttribute>(true);

                    if (attributes.Any())
                    {
                        yield return(new DataAnnotationsValidatorFrame(contextCreator.Variable, p));
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Adds a ConstructorFrame<T> to the method frames
        /// </summary>
        /// <param name="constructor"></param>
        /// <param name="configure">Optional, any additional configuration for the constructor frame</param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public FramesCollection CallConstructor <T>(Expression <Func <T> > constructor, Action <ConstructorFrame <T> > configure = null)
        {
            var frame = new ConstructorFrame <T>(constructor);

            configure?.Invoke(frame);
            Add(frame);

            return(this);
        }
        private static IEnumerable <Frame> RegisterBlueprintExceptionHandler(Variable exception)
        {
            /*
             * var validationResult = new Blueprint.Api.Middleware.ValidationResult(e.ValidationResults);
             * return validationResult;
             */
            var validationFailures = new Variable(typeof(ValidationFailures), $"{exception}.{nameof(ValidationException.ValidationResults)}");

            var createResult = new ConstructorFrame <ValidationFailedOperationResult>(() => new ValidationFailedOperationResult((ValidationFailures)null))
            {
                Parameters = { [0] = validationFailures },
            };

            yield return(createResult);

            yield return(new ReturnFrame(createResult.Variable));
        }
Example #4
0
        /// <inheritdoc />
        public void Build(MiddlewareBuilderContext context)
        {
            var properties        = context.Descriptor.Properties;
            var operationVariable = context.FindVariable(context.Descriptor.OperationType);
            var apiOperationDescriptorVariable = context.FindVariable <ApiOperationDescriptor>();
            var resultsCreator      = new ConstructorFrame <ValidationFailures>(() => new ValidationFailures());
            var hasValidationFrames = false;
            var sources             = context.ServiceProvider.GetServices <IValidationSourceBuilder>();

            void AddValidatorFrame(Frame frame)
            {
                if (!hasValidationFrames)
                {
                    // Only add the "results creator" frame if there are any actual validation calls. This is the line
                    // that creates an empty ValidationFailures
                    context.ExecuteMethod.Frames.Add(resultsCreator);

                    hasValidationFrames = true;
                }

                context.ExecuteMethod.Frames.Add(frame);
            }

            var operationProperties = new List <OperationProperty>();

            for (var i = 0; i < properties.Length; i++)
            {
                var p = properties[i];

                var propertyInfoVariable       = new PropertyInfoVariable(p, $"{apiOperationDescriptorVariable}.{nameof(ApiOperationDescriptor.Properties)}[{i}]");
                var propertyAttributesVariable = new Variable(typeof(object[]), $"{apiOperationDescriptorVariable}.{nameof(ApiOperationDescriptor.PropertyAttributes)}[{i}]");
                var propertyValueVariable      = operationVariable.GetProperty(p.Name);

                operationProperties.Add(new OperationProperty
                {
                    PropertyInfoVariable       = propertyInfoVariable,
                    PropertyValueVariable      = propertyValueVariable,
                    PropertyAttributesVariable = propertyAttributesVariable,
                });
            }

            foreach (var s in sources)
            {
                foreach (var frame in s.GetFrames(operationVariable, operationProperties))
                {
                    AddValidatorFrame(frame);
                }
            }

            // Only bother trying to validate if properties actually exist that are validated
            if (hasValidationFrames)
            {
                /*
                 * var validationFailures = _from above_;
                 *
                 * if (validationFailures.Count > 0)
                 * {
                 *     var validationResult = new ValidationResult(validationFailures);
                 *
                 *     return validationResult;
                 * }
                 */
                var createResult = new ConstructorFrame <ValidationFailedOperationResult>(() => new ValidationFailedOperationResult((ValidationFailures)null));

                var failureCount = $"{resultsCreator.Variable}.{nameof(ValidationFailures.Count)}";

                context.AppendFrames(
                    new IfBlock($"{failureCount} > 0")
                {
                    LogFrame.Debug(
                        _validationFailedLogEvent,
                        "Validation failed with {ValidationFailureCount} failures, returning ValidationFailedOperationResult",
                        new Variable <int>(failureCount)),
                    createResult,
                    new ReturnFrame(createResult.Variable),
                });
            }

            var apiOperationContext = context.FindVariable(typeof(ApiOperationContext));
            var activityVariable    = apiOperationContext.GetProperty(nameof(ApiOperationContext.Activity));

            // Always need to register extra exception handlers because the operation handler itself may do additional validation
            // and throw an exception to indicate a problem, even if the operation itself is _not_ validated
            context.RegisterUnhandledExceptionHandler(typeof(ValidationException), e => RegisterBlueprintExceptionHandler(activityVariable, e));
            context.RegisterUnhandledExceptionHandler(typeof(System.ComponentModel.DataAnnotations.ValidationException), e => RegisterDataAnnotationsExceptionHandler(activityVariable, e));
        }