public void Validate_ReturnsMemberName_IfItIsDifferentFromDisplayName()
        {
            // Arrange
            var metadata = _metadataProvider.GetMetadataForType(typeof(SampleModel));
            var model = new SampleModel();

            var attribute = new Mock<TestableValidationAttribute> { CallBase = true };
            attribute
                 .Setup(p => p.IsValidPublic(It.IsAny<object>(), It.IsAny<ValidationContext>()))
                 .Returns(new ValidationResult("Name error", new[] { "Name" }));

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: null,
                model: model);

            // Act
            var results = validator.Validate(validationContext);

            // Assert
            ModelValidationResult validationResult = Assert.Single(results);
            Assert.Equal("Name", validationResult.MemberName);
        }
        public void Validate_SetsMemberName_OnValidationContext_ForProperties(
            ModelMetadata metadata,
            object container,
            object model,
            string expectedMemberName)
        {
            // Arrange
            var attribute = new Mock<TestableValidationAttribute> { CallBase = true };
            attribute
                .Setup(p => p.IsValidPublic(It.IsAny<object>(), It.IsAny<ValidationContext>()))
                .Callback((object o, ValidationContext context) =>
                {
                    Assert.Equal(expectedMemberName, context.MemberName);
                })
                .Returns(ValidationResult.Success)
                .Verifiable();
            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: model);

            // Act
            var results = validator.Validate(validationContext);

            // Assert
            Assert.Empty(results);
            attribute.VerifyAll();
        }
        public void Validate_ReturnsSingleValidationResult_IfMemberNameSequenceIsEmpty()
        {
            // Arrange
            const string errorMessage = "Some error message";

            var metadata = _metadataProvider.GetMetadataForType(typeof(string));
            var container = "Hello";
            var model = container.Length;

            var attribute = new Mock<TestableValidationAttribute> { CallBase = true };
            attribute
                 .Setup(p => p.IsValidPublic(It.IsAny<object>(), It.IsAny<ValidationContext>()))
                 .Returns(new ValidationResult(errorMessage, memberNames: null));
            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);

            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: model);

            // Act
            var results = validator.Validate(validationContext);

            // Assert
            var validationResult = Assert.Single(results);
            Assert.Equal(errorMessage, validationResult.Message);
            Assert.Empty(validationResult.MemberName);
        }
        public void Validate_ReturnsSingleValidationResult_IfOneMemberNameIsSpecified()
        {
            // Arrange
            const string errorMessage = "A different error message";

            var metadata = _metadataProvider.GetMetadataForType(typeof(object));
            var model = new object();

            var attribute = new Mock<TestableValidationAttribute> { CallBase = true };
            attribute
                 .Setup(p => p.IsValidPublic(It.IsAny<object>(), It.IsAny<ValidationContext>()))
                 .Returns(new ValidationResult(errorMessage, new[] { "FirstName" }));

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: null,
                model: model);

            // Act
            var results = validator.Validate(validationContext);

            // Assert
            ModelValidationResult validationResult = Assert.Single(results);
            Assert.Equal(errorMessage, validationResult.Message);
            Assert.Equal("FirstName", validationResult.MemberName);
        }
예제 #5
0
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            var dbcontext = (ShopDbContext)context.ActionContext.HttpContext
                            .RequestServices.GetService(typeof(ShopDbContext));

            return(null);
        }
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            string value = context.Model as string;

            if (!string.IsNullOrEmpty(value))
            {
                if (!long.TryParse(value, out long number))
                {
                    yield return(new ModelValidationResult("", NotNumberError));
                }
                else
                {
                    if (number < 0)
                    {
                        yield return(new ModelValidationResult("", NotNumberError));
                    }
                    if (value.Length < MinLength)
                    {
                        yield return(new ModelValidationResult("", string.Format(ApplicationResources.UserInterface.ModelsValidationMessages.PhoneNumberTooShort, MinLength)));
                    }
                    if (value.Length > 25)
                    {
                        yield return(new ModelValidationResult("", string.Format(ApplicationResources.UserInterface.ModelsValidationMessages.PhoneNumberTooLong, MaxLength)));
                    }
                }
            }
        }
예제 #7
0
        public void Validate_ReturnsExpectedResults_Collection()
        {
            // Arrange
            var validator = new DataSetValidator();
            var model     = DataSet <SampleModel> .Create();

            model.AddRow();

            var metadata = _metadataProvider.GetMetadataForProperty(
                typeof(SampleModelContainer),
                nameof(SampleModelContainer.SampleModel));
            var validationContext = new ModelValidationContext(
                new ActionContext(),
                metadata,
                _metadataProvider,
                container: null,
                model: model);

            // Act
            var results      = validator.Validate(validationContext);
            var resultsArray = results.ToArray();

            // Assert
            Assert.NotNull(results);
            Assert.Single(resultsArray);
            Assert.Equal(ModelNames.CreatePropertyModelName("[0]", nameof(SampleModel.ID)), resultsArray[0].MemberName);
        }
예제 #8
0
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            IEnumerable <ModelValidationResult> result = Enumerable.Empty <ModelValidationResult>();

            // Dependancy injection does not work with attributes so manually wire up the database context.
            using (NorthwindContext dbContext = DAL.Startup.NorthwindContext)
            {
                IRepository <Category, int> categories = new CategoryRepository(dbContext);

                int?value = context.Model as int?;  // get the value of supplier (the type must match the column type)

                if (value == null)
                {
                    // a supplier id must be supplied
                    result = new List <ModelValidationResult>()
                    {
                        new ModelValidationResult("", "A category id must be provided")
                    };
                }
                else
                {
                    Category category = categories.Fetch(value.Value);

                    if (category == null)
                    {
                        result = new List <ModelValidationResult>()
                        {
                            new ModelValidationResult("", ErrorMessage)
                        };
                    }
                }
            }

            return(result);
        }
예제 #9
0
 public static IEnumerable<ModelValidationResult> Validate([NotNull] this ModelBindingContext bindingContext)
 {
     var validators = GetValidators(bindingContext, bindingContext.ModelMetadata);
     var compositeValidator = new CompositeModelValidator(validators);
     var modelValidationContext = new ModelValidationContext(bindingContext, bindingContext.ModelMetadata);
     return compositeValidator.Validate(modelValidationContext);
 }
예제 #10
0
        public virtual bool TryValidateModel([NotNull] object model, string prefix)
        {
            if (BindingContext == null)
            {
                var message = Resources.FormatPropertyOfTypeCannotBeNull(
                    nameof(BindingContext),
                    typeof(Controller).FullName);
                throw new InvalidOperationException(message);
            }

            var modelMetadata = MetadataProvider.GetMetadataForType(
                modelAccessor: () => model,
                modelType: model.GetType());

            var validationContext = new ModelValidationContext(
                MetadataProvider,
                BindingContext.ValidatorProvider,
                ModelState,
                modelMetadata,
                containerMetadata: null);

            var modelName = prefix ?? string.Empty;

            var validationNode = new ModelValidationNode(modelMetadata, modelName)
            {
                ValidateAllProperties = true
            };

            validationNode.Validate(validationContext);

            return(ModelState.IsValid);
        }
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext mvContext)
        {
            var selector    = _customizations.ToValidatorSelector();
            var interceptor = _customizations.GetInterceptor() ?? _validator as IValidatorInterceptor;
            var context     = new FluentValidation.ValidationContext(mvContext.Model,
                                                                     new FluentValidation.Internal.PropertyChain(), selector);

            if (interceptor != null)
            {
                // Allow the user to provide a customized context
                // However, if they return null then just use the original context.
                context = interceptor.BeforeMvcValidation((ControllerContext)mvContext.ActionContext, context) ??
                          context;
            }

            var result = _validator.Validate(context);

            if (interceptor != null)
            {
                // allow the user to provice a custom collection of failures, which could be empty.
                // However, if they return null then use the original collection of failures.
                result = interceptor.AfterMvcValidation((ControllerContext)mvContext.ActionContext, context, result) ??
                         result;
            }

            return(result.Errors.Select(x => new ModelValidationResult(x.PropertyName, x.ErrorMessage)));
        }
예제 #12
0
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            IEnumerable <ModelValidationResult> result = Enumerable.Empty <ModelValidationResult>();

            // Dependancy injection does not work with attributes so manually wire up the database context.
            using (NorthwindContext dbContext = DAL.Startup.NorthwindContext)
            {
                IRepository <Order, int> repository = new OrderRepository(dbContext);

                int?value = context.Model as int?;

                if (value == null)
                {
                    result = new List <ModelValidationResult>()
                    {
                        new ModelValidationResult("", "A order id must be provided")
                    };
                }
                else
                {
                    Order model = repository.Fetch(value.Value);

                    if (model == null)
                    {
                        result = new List <ModelValidationResult>()
                        {
                            new ModelValidationResult("", ErrorMessage)
                        };
                    }
                }
            }

            return(result);
        }
예제 #13
0
        public void Validate_IsValidFalse_StringLocalizerGetsArguments(
            ValidationAttribute attribute,
            string model,
            object[] values)
        {
            // Arrange
            var stringLocalizer = new Mock <IStringLocalizer>();

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute,
                stringLocalizer.Object);

            var metadata          = _metadataProvider.GetMetadataForType(typeof(SampleModel));
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: null,
                model: model);

            // Act
            validator.Validate(validationContext);

            // Assert
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(values) + " " + attribute.GetType().Name;

            stringLocalizer.Verify(l => l[LocalizationKey, values], json);
        }
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            var model = context.Model;

            if (model == null)
            {
                return(Enumerable.Empty <ModelValidationResult>());
            }

            if (!(model is IValidatableObject validatable))
            {
                throw new InvalidOperationException($"Incompatible Type:{model.GetType().FullName}");
            }

            // The constructed ValidationContext is intentionally slightly different from what
            // DataAnnotationsModelValidator creates. The instance parameter would be context.Container
            // (if non-null) in that class. But, DataAnnotationsModelValidator _also_ passes context.Model
            // separately to any ValidationAttribute.
            var validationContext = new ValidationContext(
                instance: validatable,
                serviceProvider: context.ActionContext?.HttpContext?.RequestServices,
                items: null)
            {
                DisplayName = context.ModelMetadata.GetDisplayName(),
                MemberName  = context.ModelMetadata.Name,
            };

            return(ConvertResults(validatable.Validate(validationContext)));
        }
예제 #15
0
        public void Validate_ReturnsExpectedResults(
            string errorMessage,
            IEnumerable <string> memberNames,
            IEnumerable <ModelValidationResult> expectedResults)
        {
            // Arrange
            var metadata  = _metadataProvider.GetMetadataForProperty(typeof(string), nameof(string.Length));
            var container = "Hello";
            var model     = container.Length;

            var attribute = new Mock <TestableValidationAttribute> {
                CallBase = true
            };

            attribute
            .Setup(p => p.IsValidPublic(It.IsAny <object>(), It.IsAny <ValidationContext>()))
            .Returns(new ValidationResult(errorMessage, memberNames));

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: model);

            // Act
            var results = validator.Validate(validationContext);

            // Assert
            Assert.Equal(expectedResults, results, ModelValidationResultComparer.Instance);
        }
예제 #16
0
        public void Validate_IsValidFalse_StringLocalizerReturnsLocalizerErrorMessage()
        {
            // Arrange
            var metadata  = _metadataProvider.GetMetadataForType(typeof(string));
            var container = "Hello";

            var attribute = new MaxLengthAttribute(4);

            attribute.ErrorMessage = "{0} should have no more than {1} characters.";

            var localizedString = new LocalizedString(attribute.ErrorMessage, "Longueur est invalide : 4");
            var stringLocalizer = new Mock <IStringLocalizer>();

            stringLocalizer.Setup(s => s[attribute.ErrorMessage, It.IsAny <object[]>()]).Returns(localizedString);

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute,
                stringLocalizer.Object);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: "abcde");

            // Act
            var result = validator.Validate(validationContext);

            // Assert
            var validationResult = result.Single();

            Assert.Empty(validationResult.MemberName);
            Assert.Equal("Longueur est invalide : 4", validationResult.Message);
        }
예제 #17
0
        public void Validate_Invalid()
        {
            // Arrange
            var metadata  = _metadataProvider.GetMetadataForProperty(typeof(string), "Length");
            var container = "Hello";
            var model     = container.Length;

            var attribute = new Mock <ValidationAttribute> {
                CallBase = true
            };

            attribute.Setup(a => a.IsValid(model)).Returns(false);

            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: model);

            // Act
            var result = validator.Validate(validationContext);

            // Assert
            var validationResult = result.Single();

            Assert.Empty(validationResult.MemberName);
            Assert.Equal(attribute.Object.FormatErrorMessage("Length"), validationResult.Message);
        }
예제 #18
0
        public void Validate_ValidationResultSuccess()
        {
            // Arrange
            var metadata  = _metadataProvider.GetMetadataForType(typeof(string));
            var container = "Hello";
            var model     = container.Length;

            var attribute = new Mock <TestableValidationAttribute> {
                CallBase = true
            };

            attribute
            .Setup(p => p.IsValidPublic(It.IsAny <object>(), It.IsAny <ValidationContext>()))
            .Returns(ValidationResult.Success);
            var validator = new DataAnnotationsModelValidator(
                new ValidationAttributeAdapterProvider(),
                attribute.Object,
                stringLocalizer: null);
            var validationContext = new ModelValidationContext(
                actionContext: new ActionContext(),
                modelMetadata: metadata,
                metadataProvider: _metadataProvider,
                container: container,
                model: model);

            // Act
            var result = validator.Validate(validationContext);

            // Assert
            Assert.Empty(result);
        }
        /// <summary>
        /// Validate the constraint expression.
        /// </summary>
        /// <param name="bundle">Model to validate.</param>
        /// <param name="theContext">Validation context to capture the errors.</param>
        /// <returns>
        /// Return true if the constraint is valid, return false if
        /// the constraint is not valid.
        /// </returns>
        public override bool Validate(BundleModel bundle, ModelValidationContext theContext)
        {
            if (Expression.Node == null)
            {
                return(false);
            }

            var variableCaptureVisitor = new ConstraintVariableReferenceCaptureVisitor();

            Expression.Node.AcceptVisitor(variableCaptureVisitor);
            var variableReferences = variableCaptureVisitor.GetReferences();

            foreach (var singletonVariableReference in variableReferences.SingletonVariableReferences)
            {
                if (bundle.Variables.FirstOrDefault(_ => _.Name.IsEqualTo(singletonVariableReference.VariableName)) == null)
                {
                    theContext.AddError($"Missing singleton variable {singletonVariableReference.VariableName}");
                    return(false);
                }
            }

            foreach (var aggregateVariableReference in variableReferences.AggregateVariableReferences)
            {
                if (bundle.Aggregates.FirstOrDefault(_ => _.Name.IsEqualTo(aggregateVariableReference.VariableName)) == null)
                {
                    theContext.AddError($"Missing aggregate variable {aggregateVariableReference.VariableName}");
                    return(false);
                }
            }

            return(true);
        }
예제 #20
0
        public async Task <ModelBindingResult> BindModelAsync(
            [NotNull] ParameterDescriptor parameter,
            [NotNull] ModelStateDictionary modelState,
            [NotNull] OperationBindingContext operationContext)
        {
            var metadata            = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
            var modelBindingContext = GetModelBindingContext(
                parameter.Name,
                metadata,
                parameter.BindingInfo,
                modelState,
                operationContext);

            var modelBindingResult = await operationContext.ModelBinder.BindModelAsync(modelBindingContext);

            if (modelBindingResult != null &&
                modelBindingResult.IsModelSet &&
                modelBindingResult.ValidationNode != null)
            {
                var modelExplorer = new ModelExplorer(
                    _modelMetadataProvider,
                    metadata,
                    modelBindingResult.Model);
                var validationContext = new ModelValidationContext(
                    modelBindingContext.BindingSource,
                    operationContext.ValidatorProvider,
                    modelState,
                    modelExplorer);

                _validator.Validate(validationContext, modelBindingResult.ValidationNode);
            }

            return(modelBindingResult);
        }
예제 #21
0
        protected override async Task <bool> BindAsync(
            ModelBindingContext bindingContext,
            IFormatterBinderMetadata metadata)
        {
            var formatterContext = new InputFormatterContext(_actionContext, bindingContext.ModelType);
            var formatter        = _formatterSelector.SelectFormatter(formatterContext);

            if (formatter == null)
            {
                var unsupportedContentType = Resources.FormatUnsupportedContentType(
                    bindingContext.HttpContext.Request.ContentType);
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, unsupportedContentType);

                // Should always return true so that the model binding process ends here.
                return(true);
            }

            bindingContext.Model = await formatter.ReadAsync(formatterContext);

            // Validate the deserialized object
            var validationContext = new ModelValidationContext(
                bindingContext.MetadataProvider,
                bindingContext.ValidatorProvider,
                bindingContext.ModelState,
                bindingContext.ModelMetadata,
                containerMetadata: null,
                excludeFromValidationDelegate: _mvcOptions.Options.ExcludeFromValidationDelegates);

            _bodyModelValidator.Validate(validationContext, bindingContext.ModelName);
            return(true);
        }
예제 #22
0
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            IEnumerable <ModelValidationResult> result = Enumerable.Empty <ModelValidationResult>();

            // Dependancy injection does not work with attributes so manually wire up the database context.
            using (NorthwindContext dbContext = DAL.Startup.NorthwindContext)
            {
                IRepository <Territory, string> territories = new TerritoryRepository(dbContext);

                string value = context.Model as string;

                if (value == null)
                {
                    result = new List <ModelValidationResult>()
                    {
                        new ModelValidationResult("", "A territory id must be provided")
                    };
                }
                else
                {
                    Territory territory = territories.Fetch(value);

                    if (territory == null)
                    {
                        result = new List <ModelValidationResult>()
                        {
                            new ModelValidationResult("", ErrorMessage)
                        };
                    }
                }
            }

            return(result);
        }
예제 #23
0
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext context)
        {
            if (!(context.Model is string))
            {
                return(Enumerable.Empty <ModelValidationResult>());
            }

            var str = (string)context.Model;

            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] >= 'a' && str[i] <= 'z' || str[i] >= 'A' && str[i] <= 'Z')
                {
                    continue;
                }

                return(new List <ModelValidationResult>
                {
                    new ModelValidationResult(context.ModelMetadata.PropertyName, $"{ErrorMessage}")
                });
            }
            // рефакторинг инверсией
            // рефакторинг выделение идентичных действий

            //LINQ или Regex (скорее всего второй)
            return(Enumerable.Empty <ModelValidationResult>()); // возможно выброс исключения
        }
예제 #24
0
        /// <summary>
        /// Builds a validator selector from the options specified in the attribute's properties.
        /// </summary>
        /// <param name="mvContext"></param>
        public IValidatorSelector ToValidatorSelector(ModelValidationContext mvContext)
        {
            IValidatorSelector selector;

            if (!string.IsNullOrEmpty(RuleSet))
            {
                var rulesets = RuleSet.Split(',', ';')
                               .Select(x => x.Trim())
                               .ToArray();
                selector = CreateRulesetValidatorSelector(mvContext, rulesets);
            }
            else if (!string.IsNullOrEmpty(Properties))
            {
                var properties = Properties.Split(',', ';')
                                 .Select(x => x.Trim())
                                 .ToArray();
                selector = CreateMemberNameValidatorSelector(mvContext, properties);
            }
            else
            {
                selector = CreateDefaultValidatorSelector(mvContext);
            }

            return(selector);
        }
예제 #25
0
        public void Validate_ReturnsExpectedResults(
            ValidationResult[] innerResults,
            ModelValidationResult[] expectedResults)
        {
            // Arrange
            var adapter = new ValidatableObjectAdapter();
            var model   = new SampleModel();

            foreach (var result in innerResults)
            {
                model.ValidationResults.Add(result);
            }

            var metadata = _metadataProvider.GetMetadataForProperty(
                typeof(SampleModelContainer),
                nameof(SampleModelContainer.SampleModel));
            var validationContext = new ModelValidationContext(
                new ActionContext(),
                metadata,
                _metadataProvider,
                container: null,
                model: model);

            // Act
            var results = adapter.Validate(validationContext);

            // Assert
            Assert.NotNull(results);
            Assert.Equal(expectedResults, results, ModelValidationResultComparer.Instance);
        }
예제 #26
0
        public void Validate_PassesExpectedNames(
            ModelMetadata metadata,
            string expectedDisplayName,
            string expectedMemberName)
        {
            // Arrange
            var adapter           = new ValidatableObjectAdapter();
            var model             = new SampleModel();
            var validationContext = new ModelValidationContext(
                new ActionContext(),
                metadata,
                _metadataProvider,
                container: new SampleModelContainer(),
                model: model);

            // Act
            var results = adapter.Validate(validationContext);

            // Assert
            Assert.NotNull(results);
            Assert.Empty(results);

            Assert.Equal(expectedDisplayName, model.DisplayName);
            Assert.Equal(expectedMemberName, model.MemberName);
            Assert.Equal(model, model.ObjectInstance);
        }
예제 #27
0
    public void GetErrorMessage_DontLocalizeWhenErrorMessageResourceTypeGiven()
    {
        // Arrange
        var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();

        var modelMetadata = metadataProvider.GetMetadataForProperty(typeof(string), "Length");

        var stringLocalizer = new Mock <IStringLocalizer>(MockBehavior.Loose);

        var attribute = new TestValidationAttribute();
        var adapter   = new TestValidationAttributeAdapter(attribute, stringLocalizer.Object);

        var actionContext     = new ActionContext();
        var validationContext = new ModelValidationContext(
            actionContext,
            modelMetadata,
            metadataProvider,
            container: null,
            model: null);

        // Act
        adapter.GetErrorMessage(validationContext);

        // Assert
        Assert.True(attribute.Formatted);
    }
예제 #28
0
        /// <summary>
        /// Updates the specified <paramref name="model"/> instance using the specified <paramref name="modelBinder"/>
        /// and the specified <paramref name="valueProvider"/> and executes validation using the specified
        /// <paramref name="validatorProvider"/>.
        /// </summary>
        /// <param name="model">The model instance to update and validate.</param>
        /// <param name="modelType">The type of model instance to update and validate.</param>
        /// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
        /// </param>
        /// <param name="httpContext">The <see cref="HttpContext"/> for the current executing request.</param>
        /// <param name="modelState">The <see cref="ModelStateDictionary"/> used for maintaining state and
        /// results of model-binding validation.</param>
        /// <param name="metadataProvider">The provider used for reading metadata for the model type.</param>
        /// <param name="modelBinder">The <see cref="IModelBinder"/> used for binding.</param>
        /// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
        /// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
        /// bound values.</param>
        /// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
        /// on the model instance.</param>
        /// <param name="predicate">A predicate which can be used to
        /// filter properties(for inclusion/exclusion) at runtime.</param>
        /// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
        public static async Task <bool> TryUpdateModelAsync(
            [NotNull] object model,
            [NotNull] Type modelType,
            [NotNull] string prefix,
            [NotNull] HttpContext httpContext,
            [NotNull] ModelStateDictionary modelState,
            [NotNull] IModelMetadataProvider metadataProvider,
            [NotNull] IModelBinder modelBinder,
            [NotNull] IValueProvider valueProvider,
            [NotNull] IObjectModelValidator objectModelValidator,
            [NotNull] IModelValidatorProvider validatorProvider,
            [NotNull] Func <ModelBindingContext, string, bool> predicate)
        {
            if (!modelType.IsAssignableFrom(model.GetType()))
            {
                var message = Resources.FormatModelType_WrongType(
                    model.GetType().FullName,
                    modelType.FullName);
                throw new ArgumentException(message, nameof(modelType));
            }

            var modelMetadata = metadataProvider.GetMetadataForType(modelType);

            // Clear ModelStateDictionary entries for the model so that it will be re-validated.
            ClearValidationStateForModel(modelType, modelState, metadataProvider, prefix);

            var operationBindingContext = new OperationBindingContext
            {
                ModelBinder       = modelBinder,
                ValidatorProvider = validatorProvider,
                MetadataProvider  = metadataProvider,
                HttpContext       = httpContext
            };

            var modelBindingContext = new ModelBindingContext
            {
                Model                   = model,
                ModelMetadata           = modelMetadata,
                ModelName               = prefix,
                ModelState              = modelState,
                ValueProvider           = valueProvider,
                FallbackToEmptyPrefix   = true,
                OperationBindingContext = operationBindingContext,
                PropertyFilter          = predicate
            };

            var modelBindingResult = await modelBinder.BindModelAsync(modelBindingContext);

            if (modelBindingResult != null)
            {
                var modelExplorer          = new ModelExplorer(metadataProvider, modelMetadata, modelBindingResult.Model);
                var modelValidationContext = new ModelValidationContext(modelBindingContext, modelExplorer);
                modelValidationContext.RootPrefix = prefix;
                objectModelValidator.Validate(modelValidationContext);
                return(modelState.IsValid);
            }

            return(false);
        }
        public IEnumerable <ModelValidationResult> Validate(ModelValidationContext mvContext)
        {
            // Skip validation if model is null or the model has been marked for skipping.
            if (mvContext.Model == null || ShouldSkip(mvContext))
            {
                return(Enumerable.Empty <ModelValidationResult>());
            }

            var factory = mvContext.ActionContext.HttpContext.RequestServices.GetService(typeof(IValidatorFactory)) as IValidatorFactory;

            if (factory != null)
            {
                var validator = factory.GetValidator(mvContext.ModelMetadata.ModelType);

                if (validator != null)
                {
                    var customizations = GetCustomizations(mvContext.ActionContext, mvContext.Model);

                    if (customizations.Skip)
                    {
                        return(Enumerable.Empty <ModelValidationResult>());
                    }

                    if (mvContext.Container != null)
                    {
                        var containerCustomizations = GetCustomizations(mvContext.ActionContext, mvContext.Container);
                        if (containerCustomizations.Skip)
                        {
                            return(Enumerable.Empty <ModelValidationResult>());
                        }
                    }

                    var selector    = customizations.ToValidatorSelector();
                    var interceptor = customizations.GetInterceptor() ?? (validator as IValidatorInterceptor);
                    var context     = new FluentValidation.ValidationContext(mvContext.Model, new FluentValidation.Internal.PropertyChain(), selector);
                    context.RootContextData["InvokedByMvc"] = true;

                    if (interceptor != null)
                    {
                        // Allow the user to provide a customized context
                        // However, if they return null then just use the original context.
                        context = interceptor.BeforeMvcValidation((ControllerContext)mvContext.ActionContext, context) ?? context;
                    }

                    var result = validator.Validate(context);

                    if (interceptor != null)
                    {
                        // allow the user to provice a custom collection of failures, which could be empty.
                        // However, if they return null then use the original collection of failures.
                        result = interceptor.AfterMvcValidation((ControllerContext)mvContext.ActionContext, context, result) ?? result;
                    }

                    return(result.Errors.Select(x => new ModelValidationResult(x.PropertyName, x.ErrorMessage)));
                }
            }

            return(Enumerable.Empty <ModelValidationResult>());
        }
        public void ValidateWithAValidModelHasErrorsReturnsTrue()
        {
            var sut = MakeValidModel();
            var validationContext = new ModelValidationContext();

            new ModelValidator(sut).Validate(validationContext);
            Assert.That(validationContext.HasErrors, Is.False);
        }
        public void ValidateWithAValidModelDoesNotPopulateErrors()
        {
            var sut = MakeValidModel();
            var validationContext = new ModelValidationContext();

            new ModelValidator(sut).Validate(validationContext);
            Assert.That(validationContext.Errors, Is.Empty);
        }
        protected virtual void SetProperty(
            ModelBindingContext bindingContext,
            ModelExplorer modelExplorer,
            ModelMetadata propertyMetadata,
            ModelBindingResult dtoResult,
            IModelValidator requiredValidator)
        {
            var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
            var property = bindingContext.ModelType.GetProperty(
                propertyMetadata.PropertyName,
                bindingFlags);

            if (property == null || !property.CanWrite)
            {
                // nothing to do
                return;
            }

            object value;
            var hasDefaultValue = false;
            if (dtoResult.IsModelSet)
            {
                value = dtoResult.Model;
            }
            else
            {
                hasDefaultValue = TryGetPropertyDefaultValue(property, out value);
            }

            // 'Required' validators need to run first so that we can provide useful error messages if
            // the property setters throw, e.g. if we're setting entity keys to null.
            if (value == null)
            {
                var modelStateKey = dtoResult.Key;
                var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey);
                if (validationState == ModelValidationState.Unvalidated)
                {
                    if (requiredValidator != null)
                    {
                        var propertyExplorer = modelExplorer.GetExplorerForExpression(propertyMetadata, model: null);
                        var validationContext = new ModelValidationContext(bindingContext, propertyExplorer);
                        foreach (var validationResult in requiredValidator.Validate(validationContext))
                        {
                            bindingContext.ModelState.TryAddModelError(modelStateKey, validationResult.Message);
                        }
                    }
                }
            }

            if (!dtoResult.IsModelSet && !hasDefaultValue)
            {
                // If we don't have a value, don't set it on the model and trounce a pre-initialized
                // value.
                return;
            }

            if (value != null || property.PropertyType.AllowsNullValue())
            {
                try
                {
                    property.SetValue(bindingContext.Model, value);
                }
                catch (Exception ex)
                {
                    // don't display a duplicate error message if a binding error has already occurred for this field
                    var targetInvocationException = ex as TargetInvocationException;
                    if (targetInvocationException != null &&
                        targetInvocationException.InnerException != null)
                    {
                        ex = targetInvocationException.InnerException;
                    }
                    var modelStateKey = dtoResult.Key;
                    var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey);
                    if (validationState == ModelValidationState.Unvalidated)
                    {
                        bindingContext.ModelState.AddModelError(modelStateKey, ex);
                    }
                }
            }
            else
            {
                // trying to set a non-nullable value type to null, need to make sure there's a message
                var modelStateKey = dtoResult.Key;
                var validationState = bindingContext.ModelState.GetFieldValidationState(modelStateKey);
                if (validationState == ModelValidationState.Unvalidated)
                {
                    var errorMessage = Resources.ModelBinderConfig_ValueRequired;
                    bindingContext.ModelState.TryAddModelError(modelStateKey, errorMessage);
                }
            }
        }
        private async Task PopulateArgumentsAsync(
            OperationBindingContext operationContext,
            ModelStateDictionary modelState,
            IDictionary<string, object> arguments,
            IEnumerable<ParameterDescriptor> parameterMetadata)
        {
            modelState.MaxAllowedErrors = _options.MaxModelValidationErrors;
            foreach (var parameter in parameterMetadata)
            {
                var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
                var parameterType = parameter.ParameterType;
                var modelBindingContext = GetModelBindingContext(
                    parameter.Name,
                    metadata,
                    parameter.BindingInfo,
                    modelState,
                    operationContext);

                var modelBindingResult = await operationContext.ModelBinder.BindModelAsync(modelBindingContext);
                if (modelBindingResult != null && modelBindingResult.IsModelSet)
                {
                    var modelExplorer = new ModelExplorer(
                        _modelMetadataProvider,
                        metadata,
                        modelBindingResult.Model);

                    arguments[parameter.Name] = modelBindingResult.Model;
                    var validationContext = new ModelValidationContext(
                        modelBindingResult.Key,
                        modelBindingContext.BindingSource,
                        operationContext.ValidatorProvider,
                        modelState,
                        modelExplorer);
                    _validator.Validate(validationContext);
                }
            }
        }
        // Returns true if validator execution adds a model error.
        private static bool RunValidator(
            IModelValidator validator,
            ModelBindingContext bindingContext,
            ModelExplorer propertyExplorer,
            string modelStateKey)
        {
            var validationContext = new ModelValidationContext(bindingContext, propertyExplorer);

            var addedError = false;
            foreach (var validationResult in validator.Validate(validationContext))
            {
                bindingContext.ModelState.TryAddModelError(modelStateKey, validationResult.Message);
                addedError = true;
            }

            if (!addedError)
            {
                bindingContext.ModelState.MarkFieldValid(modelStateKey);
            }

            return addedError;
        }