Example #1
0
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            var logger         = bindingContext.HttpContext.RequestServices.GetRequiredService <ILoggerFactory>();
            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType, logger);

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            if (valueProviderResult == ValueProviderResult.None)
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var stringValue = valueProviderResult.FirstValue;

            if (string.IsNullOrWhiteSpace(stringValue))
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }

            var decryptedResult = _protection.Decrypt(stringValue);

            bindingContext.Result = ModelBindingResult.Success(decryptedResult);
            return(Task.CompletedTask);
        }
    public async Task BindModel_ThousandsSeparators_LeadToErrors(Type type)
    {
        // Arrange
        var bindingContext = GetBindingContext(type);

        bindingContext.ValueProvider = new SimpleValueProvider(new CultureInfo("en-GB"))
        {
            { "theModelName", "32,000" }
        };

        var binder = new SimpleTypeModelBinder(type, NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.False(bindingContext.Result.IsModelSet);

        var entry = Assert.Single(bindingContext.ModelState);

        Assert.Equal("theModelName", entry.Key);
        Assert.Equal("32,000", entry.Value.AttemptedValue);
        Assert.Equal(ModelValidationState.Invalid, entry.Value.ValidationState);

        var error = Assert.Single(entry.Value.Errors);

        Assert.Equal("The value '32,000' is not valid.", error.ErrorMessage);
        Assert.Null(error.Exception);
    }
Example #3
0
        /// <summary>
        /// Attempts to bind a model.
        /// </summary>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

#if !NETSTANDARD1_6
            var logger         = bindingContext.HttpContext.RequestServices.GetRequiredService <ILoggerFactory>();
            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType, logger);
#else
            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType);
#endif

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueProviderResult == ValueProviderResult.None)
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var valueAsString = valueProviderResult.FirstValue;
            if (string.IsNullOrWhiteSpace(valueAsString))
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }

            var model = valueAsString.Replace((char)1610, (char)1740).Replace((char)1603, (char)1705);
            bindingContext.Result = ModelBindingResult.Success(model);
            return(Task.CompletedTask);
        }
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            if (valueProviderResult != ValueProviderResult.None)
            {
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

                var     valueAsString = valueProviderResult.FirstValue;
                decimal result;

                if (decimal.TryParse(valueAsString, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result))
                {
                    bindingContext.Result = ModelBindingResult.Success(result);
                    return(Task.CompletedTask);
                }
            }

            // If we haven't handled it, then we'll let the base SimpleTypeModelBinder handle it
            var baseBinder = new SimpleTypeModelBinder(bindingContext.ModelType, _loggerFactory);

            return(baseBinder.BindModelAsync(bindingContext));
        }
        /// <summary>
        /// Attempts to bind a model.
        /// </summary>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            var logger       = bindingContext.HttpContext.RequestServices.GetRequiredService <ILoggerFactory>();
            var binderLogger = logger.CreateLogger(nameof(PersianDateModelBinder));

            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType, logger);

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            if (valueProviderResult == ValueProviderResult.None)
            {
                binderLogger.LogError("PersianDateModelBinder error",
                                      $"There is not valueProvider for bindingContext.ModelName:`{bindingContext.ModelName}`.");
                return(fallbackBinder.BindModelAsync(bindingContext));
            }
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            DateTime?dt;

            try
            {
                var valueAsString          = valueProviderResult.FirstValue;
                var isValidPersianDateTime = !string.IsNullOrWhiteSpace(valueAsString) &&
                                             valueAsString.IsValidPersianDateTime();

                if (!isValidPersianDateTime)
                {
                    binderLogger.LogError("PersianDateModelBinder error",
                                          $"`{valueAsString}` is not a valid PersianDateTime.");

                    return(fallbackBinder.BindModelAsync(bindingContext));
                }

                dt = valueAsString?.ToGregorianDateTime();
            }
            catch (Exception ex)
            {
                var message = $"`{valueProviderResult.FirstValue}` is not a valid Persian date.";
                bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, message);

                binderLogger.LogError(ex.Demystify(), $"PersianDateModelBinder error. {message}");

                return(Task.CompletedTask);
            }

            if (Nullable.GetUnderlyingType(bindingContext.ModelType) == typeof(DateTime))
            {
                bindingContext.Result = ModelBindingResult.Success(dt);
            }
            else if (dt.HasValue)
            {
                bindingContext.Result = ModelBindingResult.Success(dt.Value);
            }
            return(Task.CompletedTask);
        }
        /// <summary>
        /// Attempts to bind a model.
        /// </summary>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType);

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            if (valueProviderResult == ValueProviderResult.None)
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var valueAsString = valueProviderResult.FirstValue;

            if (string.IsNullOrWhiteSpace(valueAsString))
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }

            var model = valueAsString.Replace((char)1610, (char)1740).Replace((char)1603, (char)1705);

            bindingContext.Result = ModelBindingResult.Success(model);
            return(Task.CompletedTask);
        }
    public async Task BindModel_ReturnsProvidedWhitespaceString_WhenNotConvertEmptyStringToNull(string value)
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(string));

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", value }
        };

        var metadataProvider = new TestModelMetadataProvider();

        metadataProvider
        .ForType(typeof(string))
        .DisplayDetails(d => d.ConvertEmptyStringToNull = false);
        bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(typeof(string));

        var binder = new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.Same(value, bindingContext.Result.Model);
        Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
    }
 public PlusDateTimeModelBinder(ModelBinderProviderContext context)
 {
     _type  = context.Metadata.ModelType;
     _clock = context.Services.GetRequiredService <IClock>();
     _simpleTypeModelBinder = new SimpleTypeModelBinder(context.Metadata.ModelType,
                                                        context.Services.GetRequiredService <ILoggerFactory>());
 }
Example #9
0
        public DateTimeBinder(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            _baseBinder = new SimpleTypeModelBinder(type);
        }
Example #10
0
 public ScrubbingModelBinder(Type type, IScrubberAttribute attribute)
 {
     if (type == null)
     {
         throw new ArgumentNullException(nameof(type));
     }
     _attribute  = attribute as IScrubberAttribute;
     _baseBinder = new SimpleTypeModelBinder(type);
 }
Example #11
0
        public DecimalModelBinder(Type type, IDecimalAttribute attribute)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            _attribute  = attribute;
            _baseBinder = new SimpleTypeModelBinder(type);
        }
Example #12
0
        public AdjustToTimeZoneModelBinder(Type type, string timeZoneIdPropertyName)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            //_attribute = attribute as IScrubberAttribute;
            _baseBinder             = new SimpleTypeModelBinder(type);
            _timeZoneIdPropertyName = timeZoneIdPropertyName;
        }
Example #13
0
        /// <summary>
        /// Attempts to bind a model.
        /// </summary>
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

#if !NETSTANDARD1_6
            var logger         = bindingContext.HttpContext.RequestServices.GetRequiredService <ILoggerFactory>();
            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType, logger);
#else
            var fallbackBinder = new SimpleTypeModelBinder(bindingContext.ModelType);
#endif

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueProviderResult == ValueProviderResult.None)
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var valueAsString = valueProviderResult.FirstValue;
            if (string.IsNullOrWhiteSpace(valueAsString))
            {
                return(fallbackBinder.BindModelAsync(bindingContext));
            }

            if (bindingContext.ModelMetadata.ModelType == typeof(int) || bindingContext.ModelMetadata.ModelType == typeof(int?))
            {
                if (valueAsString.Contains(","))
                {
                    bindingContext.Result = ModelBindingResult.Success(int.Parse(valueAsString.Replace(",", "")));
                }
                else
                {
                    bindingContext.Result = ModelBindingResult.Success(int.Parse(valueAsString));
                }
            }
            else
            {
                if (valueAsString.Contains(","))
                {
                    bindingContext.Result = ModelBindingResult.Success(long.Parse(valueAsString.Replace(",", "")));
                }
                else
                {
                    bindingContext.Result = ModelBindingResult.Success(long.Parse(valueAsString));
                }
            }

            return(Task.CompletedTask);
        }
Example #14
0
        public async Task BindModel_NullValueProviderResult_ReturnsNull()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(int));
            var binder         = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Equal(ModelBindingResult.NoResult, result);
            Assert.Empty(bindingContext.ModelState);
        }
        public async Task BindModel_ReturnsNoResult_IfTypeCannotBeConverted(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "some-value" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Equal(ModelBindingResult.NoResult, result);
        }
        public async Task BindModel_ReturnsFailure_IfTypeCanBeConverted_AndConversionFails(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "some-value" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.NotEqual(ModelBindingResult.NoResult, result);
            Assert.False(result.IsModelSet);
        }
Example #17
0
        public async Task BindModel_ReturnsNoResult_IfTypeCannotBeConverted(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "some-value" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Equal(ModelBindingResult.NoResult, result);
        }
    public async Task BindModel_ReturnsFailure_IfTypeCanBeConverted_AndConversionFails(Type destinationType)
    {
        // Arrange
        var bindingContext = GetBindingContext(destinationType);

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", "some-value" }
        };

        var binder = new SimpleTypeModelBinder(destinationType, NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.False(bindingContext.Result.IsModelSet);
    }
Example #19
0
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!context.Metadata.IsComplexType &&
                (context.Metadata.ModelType == typeof(long) || context.Metadata.ModelType == typeof(int)))
            {
                var encodingService = context.Services.GetRequiredService <IEncodingService>();
                var loggerFactory   = context.Services.GetRequiredService <ILoggerFactory>();
                var fallBackBinder  = new SimpleTypeModelBinder(context.Metadata.ModelType, loggerFactory);

                return(new AutoDecodeModelBinder(fallBackBinder, encodingService));
            }

            return(null);
        }
    public async Task BindModel_ReturnsNull_IfTrimmedValueIsEmptyString(object value)
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(string));

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", value }
        };

        var binder = new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.Null(bindingContext.Result.Model);
        Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
    }
Example #21
0
        public async Task BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(string));

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", string.Empty }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Null(result.Model);
            Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
        }
    public async Task BindModel_EmptyValueProviderResult_ReturnsFailedAndLogsSuccessfully(ModelMetadata metadata)
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(int));

        bindingContext.ModelMetadata = metadata;

        var sink          = new TestSink();
        var loggerFactory = new TestLoggerFactory(sink, enabled: true);
        var binder        = new SimpleTypeModelBinder(typeof(int), loggerFactory);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.Equal(ModelBindingResult.Failed(), bindingContext.Result);
        Assert.Empty(bindingContext.ModelState);
        Assert.Equal(3, sink.Writes.Count());
    }
Example #23
0
        public async Task BindModel_ReturnsFailure_IfTypeCanBeConverted_AndConversionFails(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "some-value" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.NotEqual(ModelBindingResult.NoResult, result);
            Assert.False(result.IsModelSet);
        }
Example #24
0
        private IModelBinder CreateBinderCoreCached(ParameterInfo parameterInfo, object token)
        {
            if (TryGetCachedBinder(parameterInfo, token, out var binder))
            {
                return(binder);
            }

            if (!CommonHelper.IsComplexType(parameterInfo.ParameterType))
            {
                binder = new SimpleTypeModelBinder(parameterInfo);
            }
            else
            {
                binder = new ComplexTypeModelBinder(parameterInfo, _serializer);
            }

            AddToCache(parameterInfo, token, binder);

            return(binder);
        }
    public async Task BindModel_ValidValueProviderResultWithProvidedCulture_ReturnsModel()
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(decimal));

        bindingContext.ValueProvider = new SimpleValueProvider(new CultureInfo("fr-FR"))
        {
            { "theModelName", "12,5" }
        };

        var binder = new SimpleTypeModelBinder(typeof(decimal), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.True(bindingContext.Result.IsModelSet);
        Assert.Equal(12.5M, bindingContext.Result.Model);
        Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
    }
    public async Task BindModel_NullableDoubleValueProviderResult_ReturnsModel()
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(double?));

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", "12.5" }
        };

        var binder = new SimpleTypeModelBinder(typeof(double?), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.True(bindingContext.Result.IsModelSet);
        Assert.Equal(12.5, bindingContext.Result.Model);
        Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
    }
Example #27
0
        public async Task BindModel_ValidValueProviderResult_ReturnsModel()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(int));

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "42" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(result.IsModelSet);
            Assert.Equal(42, result.Model);
            Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
        }
Example #28
0
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Metadata.IsComplexType)
            {
                return(null);
            }

            var fallbackBinder = new SimpleTypeModelBinder(context.Metadata.ModelType);

            if (context.Metadata.ModelType == typeof(string))
            {
                return(new PersianizeStringModelBinder(fallbackBinder));
            }
            return(fallbackBinder);
        }
    public async Task BindModel_BindsEnumModels_IfArrayElementIsStringValue()
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(IntEnum));

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", new object[] { "1" } }
        };

        var binder = new SimpleTypeModelBinder(typeof(IntEnum), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.True(bindingContext.Result.IsModelSet);
        var boundModel = Assert.IsType <IntEnum>(bindingContext.Result.Model);

        Assert.Equal(IntEnum.Value1, boundModel);
    }
Example #30
0
        public async Task BindModel_BindsFlagsEnumModels(string flagsEnumValue, int expected)
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(FlagsEnum));

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", flagsEnumValue }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelResultAsync(bindingContext);

            // Assert
            Assert.True(result.IsModelSet);
            var boundModel = Assert.IsType <FlagsEnum>(result.Model);

            Assert.Equal((FlagsEnum)expected, boundModel);
        }
    public async Task BindModel_BindsIntEnumModels(string flagsEnumValue, int expected)
    {
        // Arrange
        var bindingContext = GetBindingContext(typeof(IntEnum));

        bindingContext.ValueProvider = new SimpleValueProvider
        {
            { "theModelName", flagsEnumValue }
        };

        var binder = new SimpleTypeModelBinder(typeof(IntEnum), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.True(bindingContext.Result.IsModelSet);
        var boundModel = Assert.IsType <IntEnum>(bindingContext.Result.Model);

        Assert.Equal((IntEnum)expected, boundModel);
    }
Example #32
0
        public async Task BindModel_CreatesError_WhenTypeConversionIsNull(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);

            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", string.Empty }
            };
            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.False(result.IsModelSet);
            Assert.Null(result.Model);

            var error = Assert.Single(bindingContext.ModelState["theModelName"].Errors);

            Assert.Equal("The value '' is invalid.", error.ErrorMessage, StringComparer.Ordinal);
            Assert.Null(error.Exception);
        }
        public async Task BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState()
        {
            // Arrange
            var message = "The value 'not an integer' is not valid for theModelName.";
            var bindingContext = GetBindingContext(typeof(int));
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "not an integer" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.NotEqual(ModelBindingResult.NoResult, result);
            Assert.Null(result.Model);
            Assert.False(bindingContext.ModelState.IsValid);
            var error = Assert.Single(bindingContext.ModelState["theModelName"].Errors);
            Assert.Equal(message, error.ErrorMessage);
        }
        public async Task BindModel_BindsFlagsEnumModels(string flagsEnumValue, int expected)
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(FlagsEnum));
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", flagsEnumValue }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(result.IsModelSet);
            var boundModel = Assert.IsType<FlagsEnum>(result.Model);
            Assert.Equal((FlagsEnum)expected, boundModel);
        }
        public async Task BindModel_NullValueProviderResult_ReturnsNull()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(int));
            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Equal(ModelBindingResult.NoResult, result);
            Assert.Empty(bindingContext.ModelState);
        }
        public async Task BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(string));
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", string.Empty }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Null(result.Model);
            Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
        }
        public async Task BindModel_ValidValueProviderResult_ReturnsModel()
        {
            // Arrange
            var bindingContext = GetBindingContext(typeof(int));
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", "42" }
            };

            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(result.IsModelSet);
            Assert.Equal(42, result.Model);
            Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
        }
        public async Task BindModel_CreatesError_WhenTypeConversionIsNull(Type destinationType)
        {
            // Arrange
            var bindingContext = GetBindingContext(destinationType);
            bindingContext.ValueProvider = new SimpleValueProvider
            {
                { "theModelName", string.Empty }
            };
            var binder = new SimpleTypeModelBinder();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.False(result.IsModelSet);
            Assert.Null(result.Model);

            var error = Assert.Single(bindingContext.ModelState["theModelName"].Errors);
            Assert.Equal("The value '' is invalid.", error.ErrorMessage, StringComparer.Ordinal);
            Assert.Null(error.Exception);
        }