diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinders/BodyModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinders/BodyModelBinder.cs index 161d2a2675..7886446d0d 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinders/BodyModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinders/BodyModelBinder.cs @@ -6,8 +6,6 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Core; -using Microsoft.AspNet.Mvc.ModelBinding; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding @@ -57,6 +55,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var unsupportedContentType = Resources.FormatUnsupportedContentType( bindingContext.OperationBindingContext.HttpContext.Request.ContentType); bindingContext.ModelState.AddModelError(bindingContext.ModelName, unsupportedContentType); + + // This model binder is the only handler for the Body binding source. + // Always tell the model binding system to skip other model binders i.e. return non-null. return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } @@ -69,9 +70,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { model = GetDefaultValueForType(bindingContext.ModelType); bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex); + + // This model binder is the only handler for the Body binding source. + // Always tell the model binding system to skip other model binders i.e. return non-null. return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } + // Success // key is empty to ensure that the model name is not used as a prefix for validation. return new ModelBindingResult(model, key: string.Empty, isModelSet: true); } diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinders/ServicesModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinders/ServicesModelBinder.cs index 7942657010..7f4f948a94 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinders/ServicesModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinders/ServicesModelBinder.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices; var model = requestServices.GetRequiredService(bindingContext.ModelType); - return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, true)); + return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true)); } } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs index e9c5d11d0d..6eb0710762 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BinderTypeBasedModelBinder.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices; var createFactory = _typeActivatorCache.GetOrAdd(bindingContext.BinderType, _createFactory); var instance = createFactory(requestServices, arguments: null); - + var modelBinder = instance as IModelBinder; if (modelBinder == null) { @@ -54,12 +54,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var result = await modelBinder.BindModelAsync(bindingContext); - var modelBindingResult = result != null ? + var modelBindingResult = result != null ? new ModelBindingResult(result.Model, result.Key, result.IsModelSet) : - new ModelBindingResult(null, bindingContext.ModelName, false); + new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); - // return a non null modelbinding result here, because this binder will handle all cases where the - // model binder is specified by metadata. + // A model binder was specified by metadata and this binder handles all such cases. + // Always tell the model binding system to skip other model binders i.e. return non-null. return modelBindingResult; } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BindingSourceModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BindingSourceModelBinder.cs index 3042b6179d..26d59102d0 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BindingSourceModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/BindingSourceModelBinder.cs @@ -59,6 +59,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding /// /// A which will complete when model binding has completed. /// + /// + /// Other model binders will never run if this method is called. Return null to skip other model binders + /// but allow higher-level handling e.g. falling back to empty prefix. + /// protected abstract Task BindModelCoreAsync([NotNull] ModelBindingContext bindingContext); /// @@ -74,13 +78,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var result = await BindModelCoreAsync(context); - var modelBindingResult = - result != null ? + var modelBindingResult = + result != null ? new ModelBindingResult(result.Model, result.Key, result.IsModelSet) : - new ModelBindingResult(null, context.ModelName, false); + new ModelBindingResult(model: null, key: context.ModelName, isModelSet: false); - // Prevent other model binders from running because this model binder is the only handler for - // its binding source. + // This model binder is the only handler for its binding source. + // Always tell the model binding system to skip other model binders i.e. return non-null. return modelBindingResult; } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ByteArrayModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ByteArrayModelBinder.cs index 934aaab10d..9ba9fae61f 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ByteArrayModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ByteArrayModelBinder.cs @@ -3,7 +3,6 @@ using System; using System.Threading.Tasks; -using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding @@ -40,13 +39,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding try { var model = Convert.FromBase64String(value); - return new ModelBindingResult(model, bindingContext.ModelName, true); + return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } catch (Exception ex) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex); } + // Matched the type (byte[]) only this binder supports. + // Always tell the model binding system to skip other model binders i.e. return non-null. return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CancellationTokenModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CancellationTokenModelBinder.cs index 0eb879f649..e71e74ffe9 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CancellationTokenModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CancellationTokenModelBinder.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding if (bindingContext.ModelType == typeof(CancellationToken)) { var model = bindingContext.OperationBindingContext.HttpContext.RequestAborted; - return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, true)); + return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true)); } return Task.FromResult(null); diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CollectionModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CollectionModelBinder.cs index f5804f5a87..54cf34a56b 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CollectionModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CollectionModelBinder.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding BindComplexCollection(bindingContext); var boundCollection = await bindCollectionTask; var model = GetModel(boundCollection); - return new ModelBindingResult(model, bindingContext.ModelName, true); + return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } // Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs index 4a1d765bfe..c52bed2140 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading.Tasks; -using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding @@ -34,14 +33,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding public virtual async Task BindModelAsync([NotNull] ModelBindingContext bindingContext) { - var newBindingContext = CreateNewBindingContext(bindingContext, - bindingContext.ModelName); - + var newBindingContext = CreateNewBindingContext(bindingContext, bindingContext.ModelName); var modelBindingResult = await TryBind(newBindingContext); - if (modelBindingResult == null && !string.IsNullOrEmpty(bindingContext.ModelName) - && bindingContext.FallbackToEmptyPrefix) + + if (modelBindingResult == null && + bindingContext.FallbackToEmptyPrefix && + !string.IsNullOrEmpty(bindingContext.ModelName)) { - // fallback to empty prefix? + // Fall back to empty prefix. newBindingContext = CreateNewBindingContext(bindingContext, modelName: string.Empty); modelBindingResult = await TryBind(newBindingContext); @@ -75,13 +74,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // { // } // - // In this case, for the model parameter the key would be SimpleType instead of model.SimpleType. + // In this case, for the model parameter the key would be SimpleType instead of model.SimpleType. // (i.e here the prefix for the model key is empty). // For the id parameter the key would be id. return modelBindingResult; } } + // Fall through to update the ModelBindingResult's key. return new ModelBindingResult( modelBindingResult.Model, bindingContext.ModelName, diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormCollectionModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormCollectionModelBinder.cs index 7bdc69eb72..b915c42084 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormCollectionModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormCollectionModelBinder.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding model = new FormCollection(new Dictionary()); } - return new ModelBindingResult(model, bindingContext.ModelName, true); + return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormFileModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormFileModelBinder.cs index 9290c2e284..e573a961d8 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormFileModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/FormFileModelBinder.cs @@ -25,14 +25,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { var postedFiles = await GetFormFilesAsync(bindingContext); var value = postedFiles.FirstOrDefault(); - return new ModelBindingResult(value, bindingContext.ModelName, value != null); + return new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null); } else if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom( bindingContext.ModelType.GetTypeInfo())) { var postedFiles = await GetFormFilesAsync(bindingContext); var value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles); - return new ModelBindingResult(value, bindingContext.ModelName, value != null); + return new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null); } return null; diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs index 286d5f261a..0fa2011ab3 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/GenericModelBinder.cs @@ -22,10 +22,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding var modelBindingResult = result != null ? new ModelBindingResult(result.Model, result.Key, result.IsModelSet) : - new ModelBindingResult(null, bindingContext.ModelName, false); + new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); - // Was able to resolve a binder type, hence we should tell the model binding system to return - // true so that none of the other model binders participate. + // Were able to resolve a binder type. + // Always tell the model binding system to skip other model binders i.e. return non-null. return modelBindingResult; } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/HeaderModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/HeaderModelBinder.cs index b8a842d05b..715de76bd2 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/HeaderModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/HeaderModelBinder.cs @@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } } - return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, model != null)); + return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: model != null)); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/KeyValuePairModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/KeyValuePairModelBinder.cs index 99df8ed86f..812cf64a5a 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/KeyValuePairModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/KeyValuePairModelBinder.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Mvc.ModelBinding.Internal; @@ -25,6 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding ModelBindingHelper.CastOrDefault(keyResult.Model), ModelBindingHelper.CastOrDefault(valueResult.Model)); + // Success return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } else if (!keyResult.IsModelSet && valueResult.IsModelSet) @@ -32,6 +32,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding bindingContext.ModelState.TryAddModelError( keyResult.Key, Resources.KeyValuePair_BothKeyAndValueMustBePresent); + + // Were able to get some data for this model. + // Always tell the model binding system to skip other model binders i.e. return non-null. return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } else if (keyResult.IsModelSet && !valueResult.IsModelSet) @@ -39,10 +42,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding bindingContext.ModelState.TryAddModelError( valueResult.Key, Resources.KeyValuePair_BothKeyAndValueMustBePresent); + + // Were able to get some data for this model. + // Always tell the model binding system to skip other model binders i.e. return non-null. return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } else { + // Caller (GenericModelBinder) was able to resolve a binder type and will create a ModelBindingResult + // that exits current ModelBinding loop. return null; } } @@ -58,16 +66,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding parentBindingContext, propertyModelName, propertyModelMetadata); - propertyBindingContext.BinderModelName = propertyModelMetadata.BinderModelName; - var modelBindingResult = - await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyBindingContext); + var modelBindingResult = await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync( + propertyBindingContext); if (modelBindingResult != null) { return modelBindingResult; } + // Always return a ModelBindingResult to avoid an NRE in BindModelAsync. return new ModelBindingResult(model: default(TModel), key: propertyModelName, isModelSet: false); } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/MutableObjectModelBinder.cs index c8085ed26b..5fd4017227 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/MutableObjectModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/MutableObjectModelBinder.cs @@ -40,8 +40,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // post-processing, e.g. property setters and hooking up validation ProcessDto(bindingContext, (ComplexModelDto)result.Model); return new ModelBindingResult( - bindingContext.Model, - bindingContext.ModelName, + bindingContext.Model, + bindingContext.ModelName, isModelSet: true); } @@ -53,6 +53,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding internal async Task CanCreateModel(MutableObjectBinderContext context) { var bindingContext = context.ModelBindingContext; + var isTopLevelObject = bindingContext.ModelMetadata.ContainerType == null; var hasExplicitAlias = bindingContext.BinderModelName != null; @@ -117,7 +118,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // However, because a property might specify a custom binding source ([FromForm]), it's not correct // for us to just try bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName), // because that may include ALL value providers - that would lead us to mistakenly create the model - // when the data is coming from a source we should use (ex: value found in query string, but the + // when the data is coming from a source we should use (ex: value found in query string, but the // model has [FromForm]). // // To do this we need to enumerate the properties, and see which of them provide a binding source @@ -133,7 +134,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // If a property does not have a binding source, then it's fair game for any value provider. // // If any property meets the above conditions and has a value from valueproviders, then we'll - // create the model and try to bind it. OR if ALL properties of the model have a greedy source, + // create the model and try to bind it. OR if ALL properties of the model have a greedy source, // then we go ahead and create it. // var isAnyPropertyEnabledForValueProviderBasedBinding = false; diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeConverterModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeConverterModelBinder.cs index bc9090aa33..bdeef7fdad 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeConverterModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeConverterModelBinder.cs @@ -31,14 +31,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding { newModel = valueProviderResult.ConvertTo(bindingContext.ModelType); ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel); - return new ModelBindingResult(newModel, bindingContext.ModelName, true); + return new ModelBindingResult(newModel, bindingContext.ModelName, isModelSet: true); } catch (Exception ex) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex); } - return new ModelBindingResult(null, bindingContext.ModelName, false); + // Were able to find a converter for the type but conversion failed. + // Tell the model binding system to skip other model binders i.e. return non-null. + return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false); } } } diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeMatchModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeMatchModelBinder.cs index 9c7085054f..5574cc6eac 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeMatchModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/TypeMatchModelBinder.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); var model = valueProviderResult.RawValue; ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model); - return new ModelBindingResult(model, bindingContext.ModelName, true); + return new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true); } internal static async Task GetCompatibleValueProviderResult(ModelBindingContext context) diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/ModelBindingResult.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/ModelBindingResult.cs index afb14eb06d..e9b056ecb6 100644 --- a/src/Microsoft.AspNet.Mvc.ModelBinding/ModelBindingResult.cs +++ b/src/Microsoft.AspNet.Mvc.ModelBinding/ModelBindingResult.cs @@ -23,22 +23,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding } /// - /// Gets or sets the model associated with this context. + /// Gets the model associated with this context. /// public object Model { get; } /// - /// Gets or sets the model name which was used to bind the model. - /// + /// + /// Gets the model name which was used to bind the model. + /// + /// /// This property can be used during validation to add model state for a bound model. + /// /// public string Key { get; } /// - /// Gets or sets a value indicating whether or not the value has been set. - /// + /// + /// Gets a value indicating whether or not the value has been set. + /// + /// /// This property can be used to distinguish between a model binder which does not find a value and /// the case where a model binder sets the null value. + /// /// public bool IsModelSet { get; } } diff --git a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs index 9917d25936..c19c2fc1b2 100644 --- a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs @@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim if (bindingContext.ModelType == typeof(HttpRequestMessage)) { var model = bindingContext.OperationBindingContext.HttpContext.GetHttpRequestMessage(); - return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, true)); + return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true)); } return Task.FromResult(null); diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs index f03272a129..daeb239ff4 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs @@ -4,7 +4,6 @@ #if DNX451 using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Moq; @@ -25,11 +24,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.BindModelAsync(bindingContext); + var result = await binder.BindModelAsync(bindingContext); // Assert - Assert.NotNull(retVal); - Assert.Null(retVal.Model); + Assert.NotNull(result); + Assert.Null(result.Model); Assert.False(bindingContext.ModelState.IsValid); Assert.Equal("someName", bindingContext.ModelName); var error = Assert.Single(bindingContext.ModelState["someName.Key"].Errors); @@ -47,11 +46,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.BindModelAsync(bindingContext); + var result = await binder.BindModelAsync(bindingContext); // Assert - Assert.NotNull(retVal); - Assert.Null(retVal.Model); + Assert.NotNull(result); + Assert.Null(result.Model); Assert.False(bindingContext.ModelState.IsValid); Assert.Equal("someName", bindingContext.ModelName); Assert.Equal(bindingContext.ModelState["someName.Value"].Errors.First().ErrorMessage, "A value is required."); @@ -73,10 +72,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.BindModelAsync(bindingContext); + var result = await binder.BindModelAsync(bindingContext); // Assert - Assert.Null(retVal); + Assert.Null(result); Assert.True(bindingContext.ModelState.IsValid); Assert.Equal(0, bindingContext.ModelState.ErrorCount); } @@ -92,11 +91,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.BindModelAsync(bindingContext); + var result = await binder.BindModelAsync(bindingContext); // Assert - Assert.NotNull(retVal); - Assert.Equal(new KeyValuePair(42, "some-value"), retVal.Model); + Assert.NotNull(result); + Assert.Equal(new KeyValuePair(42, "some-value"), result.Model); } [Fact] @@ -107,11 +106,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.TryBindStrongModel(bindingContext, "key"); + var result = await binder.TryBindStrongModel(bindingContext, "key"); // Assert - Assert.True(retVal.IsModelSet); - Assert.Equal(42, retVal.Model); + Assert.True(result.IsModelSet); + Assert.Equal(42, result.Model); Assert.Empty(bindingContext.ModelState); } @@ -133,11 +132,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test var binder = new KeyValuePairModelBinder(); // Act - var retVal = await binder.TryBindStrongModel(bindingContext, "key"); + var result = await binder.TryBindStrongModel(bindingContext, "key"); // Assert - Assert.True(retVal.IsModelSet); - Assert.Null(retVal.Model); + Assert.True(result.IsModelSet); + Assert.Null(result.Model); Assert.Empty(bindingContext.ModelState); } diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs index 297f717c32..7e7a689c4a 100644 --- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs +++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/MutableObjectModelBinderTest.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNet.Http.Core; using Microsoft.AspNet.Testing; @@ -106,17 +105,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding [Fact] public async Task CanCreateModel_ReturnsFalse_ForNonTopLevelModel_IfModelIsMarkedWithBinderMetadata() { + // Get the property metadata so that it is not a top level object. var modelMetadata = GetMetadataForType(typeof(Document)) - .Properties - .First(metadata => metadata.PropertyName == nameof(Document.SubDocument)); + .Properties + .First(metadata => metadata.PropertyName == nameof(Document.SubDocument)); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { - // Get the property metadata so that it is not a top level object. - ModelMetadata = GetMetadataForType(typeof(Document)) - .Properties - .First(metadata => metadata.PropertyName == nameof(Document.SubDocument)), + ModelMetadata = modelMetadata, OperationBindingContext = new OperationBindingContext { ValidatorProvider = Mock.Of(), @@ -381,7 +378,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding .Verifiable(); testableBinder .Setup(o => o.GetMetadataForProperties(bindingContext)) - .Returns(new ModelMetadata[0]); + .Returns(new ModelMetadata[0]); // Act var retValue = await testableBinder.Object.BindModelAsync(bindingContext); @@ -389,8 +386,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Assert Assert.NotNull(retValue); Assert.True(retValue.IsModelSet); - Assert.Same(model, retValue.Model); - Assert.IsType(retValue.Model); + var returnedPerson = Assert.IsType(retValue.Model); + Assert.Same(model, returnedPerson); testableBinder.Verify(); } @@ -442,8 +439,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Assert Assert.NotNull(retValue); Assert.True(retValue.IsModelSet); - Assert.Same(model, retValue.Model); - Assert.IsType(retValue.Model); + var returnedPerson = Assert.IsType(retValue.Model); + Assert.Same(model, returnedPerson); testableBinder.Verify(); }