public async Task TryCreateAsync_AddsModelStateError_WhenValueProviderFactoryThrowsValueProviderException()
    {
        // Arrange
        var factory = new Mock <IValueProviderFactory>();

        factory.Setup(f => f.CreateValueProviderAsync(It.IsAny <ValueProviderFactoryContext>())).ThrowsAsync(new ValueProviderException("Some error"));
        var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor(), new ModelStateDictionary());

        // Act
        var(success, result) = await CompositeValueProvider.TryCreateAsync(actionContext, new[] { factory.Object });

        // Assert
        Assert.False(success);
        var modelState = actionContext.ModelState;

        Assert.False(modelState.IsValid);
        var entry = Assert.Single(modelState);

        Assert.Empty(entry.Key);
    }
Пример #2
0
    public static PageHandlerBinderDelegate CreateHandlerBinder(
        ParameterBinder parameterBinder,
        IModelMetadataProvider modelMetadataProvider,
        IModelBinderFactory modelBinderFactory,
        CompiledPageActionDescriptor actionDescriptor,
        HandlerMethodDescriptor handler,
        MvcOptions mvcOptions)
    {
        if (handler.Parameters == null || handler.Parameters.Count == 0)
        {
            return(NullHandlerBinder);
        }

        var handlerType          = actionDescriptor.HandlerTypeInfo.AsType();
        var parameterBindingInfo = new BinderItem[handler.Parameters.Count];

        for (var i = 0; i < parameterBindingInfo.Length; i++)
        {
            var           parameter = handler.Parameters[i];
            ModelMetadata metadata;
            if (modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase)
            {
                // The default model metadata provider derives from ModelMetadataProvider
                // and can therefore supply information about attributes applied to parameters.
                metadata = modelMetadataProviderBase.GetMetadataForParameter(parameter.ParameterInfo);
            }
            else
            {
                // For backward compatibility, if there's a custom model metadata provider that
                // only implements the older IModelMetadataProvider interface, access the more
                // limited metadata information it supplies. In this scenario, validation attributes
                // are not supported on parameters.
                metadata = modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
            }

            var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext
            {
                BindingInfo = parameter.BindingInfo,
                Metadata    = metadata,
                CacheToken  = parameter,
            });

            parameterBindingInfo[i] = new BinderItem(binder, metadata);
        }

        return(Bind);

        async Task Bind(PageContext pageContext, IDictionary <string, object?> arguments)
        {
            var(success, valueProvider) = await CompositeValueProvider.TryCreateAsync(pageContext, pageContext.ValueProviderFactories);

            if (!success)
            {
                return;
            }

            for (var i = 0; i < parameterBindingInfo.Length; i++)
            {
                var parameter     = handler.Parameters[i];
                var bindingInfo   = parameterBindingInfo[i];
                var modelMetadata = bindingInfo.ModelMetadata;

                if (!modelMetadata.IsBindingAllowed)
                {
                    continue;
                }

                var result = await parameterBinder.BindModelAsync(
                    pageContext,
                    bindingInfo.ModelBinder,
                    valueProvider !,
                    parameter,
                    modelMetadata,
                    value : null,
                    container : null); // Parameters do not have containers.

                if (result.IsModelSet)
                {
                    arguments[parameter.Name] = result.Model;
                }
            }
        }
    }
Пример #3
0
    public static Func <PageContext, object, Task> CreatePropertyBinder(
        ParameterBinder parameterBinder,
        IModelMetadataProvider modelMetadataProvider,
        IModelBinderFactory modelBinderFactory,
        CompiledPageActionDescriptor actionDescriptor)
    {
        if (parameterBinder == null)
        {
            throw new ArgumentNullException(nameof(parameterBinder));
        }

        if (actionDescriptor == null)
        {
            throw new ArgumentNullException(nameof(actionDescriptor));
        }

        var properties = actionDescriptor.BoundProperties;

        if (properties == null || properties.Count == 0)
        {
            return(NullPropertyBinder);
        }

        var handlerType         = actionDescriptor.HandlerTypeInfo.AsType();
        var propertyBindingInfo = new BinderItem[properties.Count];

        for (var i = 0; i < properties.Count; i++)
        {
            var property = properties[i];
            var metadata = modelMetadataProvider.GetMetadataForProperty(handlerType, property.Name);
            var binder   = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext
            {
                BindingInfo = property.BindingInfo,
                Metadata    = metadata,
                CacheToken  = property,
            });

            propertyBindingInfo[i] = new BinderItem(binder, metadata);
        }

        return(Bind);

        async Task Bind(PageContext pageContext, object instance)
        {
            var(success, valueProvider) = await CompositeValueProvider.TryCreateAsync(pageContext, pageContext.ValueProviderFactories);

            if (!success)
            {
                return;
            }

            for (var i = 0; i < properties.Count; i++)
            {
                var property      = properties[i];
                var bindingInfo   = propertyBindingInfo[i];
                var modelMetadata = bindingInfo.ModelMetadata;

                if (!modelMetadata.IsBindingAllowed)
                {
                    continue;
                }

                var result = await parameterBinder.BindModelAsync(
                    pageContext,
                    bindingInfo.ModelBinder,
                    valueProvider !,
                    property,
                    modelMetadata,
                    value : null,
                    container : instance);

                if (result.IsModelSet)
                {
                    PropertyValueSetter.SetValue(bindingInfo.ModelMetadata, instance, result.Model);
                }
            }
        }
    }
Пример #4
0
    public static ControllerBinderDelegate?CreateBinderDelegate(
        ParameterBinder parameterBinder,
        IModelBinderFactory modelBinderFactory,
        IModelMetadataProvider modelMetadataProvider,
        ControllerActionDescriptor actionDescriptor,
        MvcOptions mvcOptions)
    {
        if (parameterBinder == null)
        {
            throw new ArgumentNullException(nameof(parameterBinder));
        }

        if (modelBinderFactory == null)
        {
            throw new ArgumentNullException(nameof(modelBinderFactory));
        }

        if (modelMetadataProvider == null)
        {
            throw new ArgumentNullException(nameof(modelMetadataProvider));
        }

        if (actionDescriptor == null)
        {
            throw new ArgumentNullException(nameof(actionDescriptor));
        }

        if (mvcOptions == null)
        {
            throw new ArgumentNullException(nameof(mvcOptions));
        }

        var parameterBindingInfo = GetParameterBindingInfo(
            modelBinderFactory,
            modelMetadataProvider,
            actionDescriptor);
        var propertyBindingInfo = GetPropertyBindingInfo(modelBinderFactory, modelMetadataProvider, actionDescriptor);

        if (parameterBindingInfo == null && propertyBindingInfo == null)
        {
            return(null);
        }

        var parameters = actionDescriptor.Parameters switch
        {
            List <ParameterDescriptor> list => list.ToArray(),
            _ => actionDescriptor.Parameters.ToArray()
        };

        var properties = actionDescriptor.BoundProperties switch
        {
            List <ParameterDescriptor> list => list.ToArray(),
            _ => actionDescriptor.BoundProperties.ToArray()
        };

        return(Bind);

        async Task Bind(ControllerContext controllerContext, object controller, Dictionary <string, object?> arguments)
        {
            var(success, valueProvider) = await CompositeValueProvider.TryCreateAsync(controllerContext, controllerContext.ValueProviderFactories);

            if (!success)
            {
                return;
            }

            Debug.Assert(valueProvider is not null);

            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter     = parameters[i];
                var bindingInfo   = parameterBindingInfo ![i];
                var modelMetadata = bindingInfo.ModelMetadata;

                if (!modelMetadata.IsBindingAllowed)
                {
                    continue;
                }

                var result = await parameterBinder.BindModelAsync(
                    controllerContext,
                    bindingInfo.ModelBinder,
                    valueProvider,
                    parameter,
                    modelMetadata,
                    value : null,
                    container : null); // Parameters do not have containers.

                if (result.IsModelSet)
                {
                    arguments[parameter.Name] = result.Model;
                }
            }

            for (var i = 0; i < properties.Length; i++)
            {
                var property      = properties[i];
                var bindingInfo   = propertyBindingInfo ![i];
Пример #5
0
        public static ControllerBinderDelegate CreateBinderDelegate(
            ParameterBinder parameterBinder,
            IModelBinderFactory modelBinderFactory,
            IModelMetadataProvider modelMetadataProvider,
            ControllerActionDescriptor actionDescriptor,
            MvcOptions mvcOptions)
        {
            if (parameterBinder == null)
            {
                throw new ArgumentNullException(nameof(parameterBinder));
            }

            if (modelBinderFactory == null)
            {
                throw new ArgumentNullException(nameof(modelBinderFactory));
            }

            if (modelMetadataProvider == null)
            {
                throw new ArgumentNullException(nameof(modelMetadataProvider));
            }

            if (actionDescriptor == null)
            {
                throw new ArgumentNullException(nameof(actionDescriptor));
            }

            if (mvcOptions == null)
            {
                throw new ArgumentNullException(nameof(mvcOptions));
            }

            var parameterBindingInfo = GetParameterBindingInfo(
                modelBinderFactory,
                modelMetadataProvider,
                actionDescriptor,
                mvcOptions);
            var propertyBindingInfo = GetPropertyBindingInfo(modelBinderFactory, modelMetadataProvider, actionDescriptor);

            if (parameterBindingInfo == null && propertyBindingInfo == null)
            {
                return(null);
            }

            return(Bind);

            async Task Bind(ControllerContext controllerContext, object controller, Dictionary <string, object> arguments)
            {
                var(success, valueProvider) = await CompositeValueProvider.TryCreateAsync(controllerContext, controllerContext.ValueProviderFactories);

                if (!success)
                {
                    return;
                }

                var parameters = actionDescriptor.Parameters;

                for (var i = 0; i < parameters.Count; i++)
                {
                    var parameter     = parameters[i];
                    var bindingInfo   = parameterBindingInfo[i];
                    var modelMetadata = bindingInfo.ModelMetadata;

                    if (!modelMetadata.IsBindingAllowed)
                    {
                        continue;
                    }

                    var result = await parameterBinder.BindModelAsync(
                        controllerContext,
                        bindingInfo.ModelBinder,
                        valueProvider,
                        parameter,
                        modelMetadata,
                        value : null);

                    if (result.IsModelSet)
                    {
                        arguments[parameter.Name] = result.Model;
                    }
                }

                var properties = actionDescriptor.BoundProperties;

                for (var i = 0; i < properties.Count; i++)
                {
                    var property      = properties[i];
                    var bindingInfo   = propertyBindingInfo[i];
                    var modelMetadata = bindingInfo.ModelMetadata;

                    if (!modelMetadata.IsBindingAllowed)
                    {
                        continue;
                    }

                    var result = await parameterBinder.BindModelAsync(
                        controllerContext,
                        bindingInfo.ModelBinder,
                        valueProvider,
                        property,
                        modelMetadata,
                        value : null);

                    if (result.IsModelSet)
                    {
                        PropertyValueSetter.SetValue(bindingInfo.ModelMetadata, controller, result.Model);
                    }
                }
            }
        }