public void CreateBindingDetails_FindsModelName()
    {
        // Arrange
        var attributes = new object[]
        {
            new ModelBinderAttribute()
            {
                Name = "Product"
            },
            new ModelBinderAttribute()
            {
                Name = "Order"
            },
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForType(typeof(string)),
            new ModelAttributes(attributes, null, null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.Equal("Product", context.BindingMetadata.BinderModelName);
    }
    public void CreateBindingDetails_FindsBinderTypeProvider_IfNullFallsBack()
    {
        // Arrange
        var attributes = new object[]
        {
            new ModelBinderAttribute(),
            new ModelBinderAttribute()
            {
                BinderType = typeof(HeaderModelBinder)
            },
            new ModelBinderAttribute()
            {
                BinderType = typeof(ArrayModelBinder <string>)
            },
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForType(typeof(string)),
            new ModelAttributes(attributes, null, null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.Equal(typeof(HeaderModelBinder), context.BindingMetadata.BinderType);
    }
    public void CreateBindingDetails_BindingBehaviorLeftAlone_ForAttributeOnPropertyType(bool initialValue)
    {
        // Arrange
        var typeAttributes = new object[]
        {
            new BindingBehaviorAttribute(BindingBehavior.Required),
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
            new ModelAttributes(typeAttributes, new object[0], null));

        // These values shouldn't be changed since this is a Type-Metadata
        context.BindingMetadata.IsBindingAllowed  = initialValue;
        context.BindingMetadata.IsBindingRequired = initialValue;

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.Equal(initialValue, context.BindingMetadata.IsBindingAllowed);
        Assert.Equal(initialValue, context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_FindsCustomAttributes_OnParameter()
    {
        // Arrange
        var parameterAttributes = new object[]
        {
            new CustomAttribute {
                Identifier = "Instance1"
            },
            new CustomAttribute {
                Identifier = "Instance2"
            }
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForParameter(ParameterInfos.SampleParameterInfo),
            new ModelAttributes(Array.Empty <object>(), null, parameterAttributes));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.Collection(context.Attributes,
                          a => Assert.Equal("Instance1", ((CustomAttribute)a).Identifier),
                          a => Assert.Equal("Instance2", ((CustomAttribute)a).Identifier));
        Assert.Equal(2, context.ParameterAttributes.Count);
    }
    public void CreateBindingDetails_OverrideBehaviorOnBaseClass_OverrideWithRequired_OnClass()
    {
        // Arrange
        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForProperty(typeof(BindRequiredOverridesInheritedBindNever).GetProperty(nameof(BindRequiredOverridesInheritedBindNever.Property)), typeof(int), typeof(BindRequiredOverridesInheritedBindNever)),
            new ModelAttributes(new object[0], new object[0], null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.True(context.BindingMetadata.IsBindingAllowed);
        Assert.True(context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_FindsBindNever_OnBaseClass()
    {
        // Arrange
        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForProperty(typeof(BindNeverOnClass).GetProperty(nameof(BindNeverOnClass.Property)), typeof(int), typeof(BindNeverOnClass)),
            new ModelAttributes(new object[0], new object[0], null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.False(context.BindingMetadata.IsBindingAllowed);
        Assert.False(context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_OverrideBehaviorOnClass_OverrideWithNever()
    {
        // Arrange
        var propertyAttributes = new object[]
        {
            new BindNeverAttribute(),
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForProperty(typeof(BindRequiredOnClass).GetProperty(nameof(BindRequiredOnClass.Property)), typeof(int), typeof(BindRequiredOnClass)),
            new ModelAttributes(new object[0], propertyAttributes, null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.False(context.BindingMetadata.IsBindingAllowed);
        Assert.False(context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_FindsBindRequired_OnParameter()
    {
        // Arrange
        var parameterAttributes = new object[]
        {
            new BindRequiredAttribute(),
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForParameter(ParameterInfos.SampleParameterInfo),
            new ModelAttributes(Array.Empty <object>(), null, parameterAttributes));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.True(context.BindingMetadata.IsBindingAllowed);
        Assert.True(context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_FindsBindRequired_OnProperty()
    {
        // Arrange
        var propertyAttributes = new object[]
        {
            new BindRequiredAttribute(),
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForProperty(typeof(string).GetProperty(nameof(string.Length)), typeof(int), typeof(string)),
            new ModelAttributes(new object[0], propertyAttributes, null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.True(context.BindingMetadata.IsBindingAllowed);
        Assert.True(context.BindingMetadata.IsBindingRequired);
    }
    public void CreateBindingDetails_FindsBindingSource()
    {
        // Arrange
        var attributes = new object[]
        {
            new BindingSourceModelBinderAttribute(BindingSource.Body),
            new BindingSourceModelBinderAttribute(BindingSource.Query),
        };

        var context = new BindingMetadataProviderContext(
            ModelMetadataIdentity.ForType(typeof(string)),
            new ModelAttributes(attributes, null, null));

        var provider = new DefaultBindingMetadataProvider();

        // Act
        provider.CreateBindingMetadata(context);

        // Assert
        Assert.Equal(BindingSource.Body, context.BindingMetadata.BindingSource);
    }