// internal for unit testing
    internal static PageBoundPropertyDescriptor[] CreateBoundProperties(PageApplicationModel applicationModel)
    {
        var results    = new List <PageBoundPropertyDescriptor>();
        var properties = applicationModel.HandlerProperties;

        for (var i = 0; i < properties.Count; i++)
        {
            var propertyModel = properties[i];

            // Only add properties which are explicitly marked to bind.
            if (propertyModel.BindingInfo == null)
            {
                continue;
            }

            var descriptor = new PageBoundPropertyDescriptor
            {
                Property      = propertyModel.PropertyInfo,
                Name          = propertyModel.PropertyName,
                BindingInfo   = propertyModel.BindingInfo,
                ParameterType = propertyModel.PropertyInfo.PropertyType,
            };

            results.Add(descriptor);
        }

        return(results.ToArray());
    }
        public async Task BindModelAsync_WithBindPageProperty_EnforcesBindRequired(int?input, bool isValid)
        {
            // Arrange
            var propertyInfo       = typeof(TestPage).GetProperty(nameof(TestPage.BindRequiredProperty));
            var propertyDescriptor = new PageBoundPropertyDescriptor
            {
                BindingInfo = BindingInfo.GetBindingInfo(new[]
                {
                    new FromQueryAttribute {
                        Name = propertyInfo.Name
                    },
                }),
                Name          = propertyInfo.Name,
                ParameterType = propertyInfo.PropertyType,
                Property      = propertyInfo,
            };

            var typeInfo         = typeof(TestPage).GetTypeInfo();
            var actionDescriptor = new CompiledPageActionDescriptor
            {
                BoundProperties = new[] { propertyDescriptor },
                HandlerTypeInfo = typeInfo,
                ModelTypeInfo   = typeInfo,
                PageTypeInfo    = typeInfo,
            };

            var testContext = ModelBindingTestHelper.GetTestContext(request =>
            {
                request.Method = "POST";
                if (input.HasValue)
                {
                    request.QueryString = new QueryString($"?{propertyDescriptor.Name}={input.Value}");
                }
            });

            var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var parameterBinder       = ModelBindingTestHelper.GetParameterBinder(modelMetadataProvider);
            var modelBinderFactory    = ModelBindingTestHelper.GetModelBinderFactory(modelMetadataProvider);
            var modelMetadata         = modelMetadataProvider
                                        .GetMetadataForProperty(typeof(TestPage), propertyDescriptor.Name);

            var pageBinder = PageBinderFactory.CreatePropertyBinder(
                parameterBinder,
                modelMetadataProvider,
                modelBinderFactory,
                actionDescriptor);
            var pageContext = new PageContext
            {
                ActionDescriptor       = actionDescriptor,
                HttpContext            = testContext.HttpContext,
                RouteData              = testContext.RouteData,
                ValueProviderFactories = testContext.ValueProviderFactories,
            };

            var page = new TestPage();

            // Act
            await pageBinder(pageContext, page);

            // Assert
            Assert.Equal(isValid, pageContext.ModelState.IsValid);
            if (isValid)
            {
                Assert.Equal(input.Value, page.BindRequiredProperty);
            }
        }