diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs index f759776be4..1cc67fb877 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeModelBinder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; @@ -39,6 +40,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding !string.IsNullOrEmpty(bindingContext.ModelName); var newBindingContext = CreateNewBindingContext(bindingContext, bindingContext.ModelName); + if (newBindingContext == null) + { + // Unable to find a value provider for this binding source. Binding will fail. + return null; + } + newBindingContext.IsFirstChanceBinding = isFirstChanceBinding; var modelBindingResult = await TryBind(newBindingContext); @@ -46,12 +53,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { // Fall back to empty prefix. newBindingContext = CreateNewBindingContext(bindingContext, modelName: string.Empty); + Debug.Assert(newBindingContext != null, "Should have failed on first attempt."); + modelBindingResult = await TryBind(newBindingContext); } if (modelBindingResult == null) { - return null; // something went wrong + // Unable to bind or something went wrong. + return null; } bindingContext.OperationBindingContext.BodyBindingState = @@ -176,6 +186,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding if (valueProvider != null) { newBindingContext.ValueProvider = valueProvider.Filter(bindingSource); + if (newBindingContext.ValueProvider == null) + { + // Unable to find a value provider for this binding source. + return null; + } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs index 7508513b57..fdbaff8e59 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/CompositeValueProvider.cs @@ -137,6 +137,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } } + if (filteredValueProviders.Count == 0) + { + // Do not create an empty CompositeValueProvider. + return null; + } + if (filteredValueProviders.Count == Count) { // No need for a new CompositeValueProvider. diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs index fb52d0a093..a86826e433 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs @@ -115,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding private async Task CanValueBindAnyModelProperties(MutableObjectBinderContext context) { - // If there are no properties on the model, there is nothing to bind. We are here means this is not a top + // If there are no properties on the model, there is nothing to bind. We are here means this is not a top // level object. So we return false. if (context.PropertyMetadata == null || context.PropertyMetadata.Count == 0) { @@ -196,6 +196,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding if (rootValueProvider != null) { valueProvider = rootValueProvider.Filter(bindingSource); + if (valueProvider == null) + { + // Unable to find a value provider for this binding source. Binding will fail. + return false; + } } } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/CompositeValueProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/CompositeValueProviderTest.cs index c341a04f9f..6537336403 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/CompositeValueProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/CompositeValueProviderTest.cs @@ -28,14 +28,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding return new CompositeValueProvider(new[] { emptyValueProvider, valueProvider }); } - protected override void CheckFilterExcludeResult(IValueProvider result) - { - // CompositeValueProvider returns an empty instance rather than null. CompositeModelBinder and - // MutableObjectModelBinder depend on this empty instance. - var compositeProvider = Assert.IsType(result); - Assert.Empty(compositeProvider); - } - #if DNX451 [Fact] public async Task GetKeysFromPrefixAsync_ReturnsResultFromFirstValueProviderThatReturnsValues() diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/EnumerableValueProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/EnumerableValueProviderTest.cs index 6cd11dd52f..9fdaf664f6 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/EnumerableValueProviderTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/EnumerableValueProviderTest.cs @@ -273,11 +273,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var result = provider.Filter(bindingSource); // Assert - CheckFilterExcludeResult(result); - } - - protected virtual void CheckFilterExcludeResult(IValueProvider result) - { Assert.Null(result); }