diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs index 8fd3074589..50c0149cc2 100644 --- a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs +++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs @@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public abstract string ModelName { get; set; } /// - /// Gets or sets the used to capture values + /// Gets or sets the used to capture values /// for properties in the object graph of the model when binding. /// /// @@ -117,21 +117,33 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public abstract ModelBindingResult Result { get; set; } /// - /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding properties - /// or collection items. + /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding + /// properties or collection items. /// - /// to assign to the property. + /// + /// to assign to the property. + /// /// Name to assign to the property. /// Name to assign to the property. /// Instance to assign to the property. - /// A scope object which should be used in a using statement where PushContext is called. - public abstract NestedScope EnterNestedScope(ModelMetadata modelMetadata, string fieldName, string modelName, object model); + /// + /// A scope object which should be used in a using statement where + /// is called. + /// + public abstract NestedScope EnterNestedScope( + ModelMetadata modelMetadata, + string fieldName, + string modelName, + object model); /// - /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding properties - /// or collection items. + /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding + /// properties or collection items. /// - /// A scope object which should be used in a using statement where PushContext is called. + /// + /// A scope object which should be used in a using statement where + /// is called. + /// public abstract NestedScope EnterNestedScope(); /// @@ -141,7 +153,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Return value of . Should be disposed - /// by caller when child binding context state should be popped off of + /// by caller when child binding context state should be popped off of /// the . /// public struct NestedScope : IDisposable diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs index 5ece146fbe..b73eab4f77 100644 --- a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs +++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs @@ -50,17 +50,26 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public abstract bool IsContainerNode { get; } /// - /// Gets the for a sub-property with the specified . + /// Gets the for a sub-property with the specified + /// . /// /// The property name to lookup. - /// The if a sub-property was found; otherwise null. - /// This method returns any existing entry, even those with with value true.. + /// + /// The if a sub-property was found; otherwise . + /// + /// + /// This method returns any existing entry, even those with with value + /// . + /// public abstract ModelStateEntry GetModelStateForProperty(string propertyName); /// /// Gets the values for sub-properties. /// - /// This method returns all existing entries, even those with with value true. + /// + /// This property returns all existing entries, even those with with value + /// . + /// public abstract IReadOnlyList Children { get; } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs index f1b8dedb84..5648576fd6 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs @@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { _stack.Push(_state); - Result = default(ModelBindingResult); + Result = default; return new NestedScope(this); } @@ -338,6 +338,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public bool IsTopLevelObject; public ModelBindingResult Result; - }; + } } } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs index 80bcedbc3a..f33deed4cc 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs @@ -143,6 +143,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (formatter == null) { _logger?.NoInputFormatterSelected(formatterContext); + var message = Resources.FormatUnsupportedContentType(httpContext.Request.ContentType); var exception = new UnsupportedContentTypeException(message); bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata); @@ -152,7 +153,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders try { var result = await formatter.ReadAsync(formatterContext); - var model = result.Model; if (result.HasError) { @@ -162,6 +162,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders if (result.IsModelSet) { + var model = result.Model; bindingContext.Result = ModelBindingResult.Success(model); } else diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs index c9699ec62b..2e551e5867 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs @@ -181,6 +181,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders bindingContext.ValueProvider }; + // Enter new scope to change ModelMetadata and isolate element binding operations. using (bindingContext.EnterNestedScope( elementMetadata, fieldName: bindingContext.FieldName, @@ -238,8 +239,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { var fullChildName = ModelNames.CreateIndexModelName(bindingContext.ModelName, indexName); - var didBind = false; - object boundValue = null; ModelBindingResult? result; using (bindingContext.EnterNestedScope( elementMetadata, @@ -251,6 +250,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders result = bindingContext.Result; } + var didBind = false; + object boundValue = null; if (result != null && result.Value.IsModelSet) { didBind = true; @@ -296,10 +297,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// /// of the model. /// - /// Collection of values retrieved from value providers. Or null if nothing was bound. + /// Collection of values retrieved from value providers. if nothing was bound. /// /// - /// An assignable to . Or null if nothing was bound. + /// An assignable to . if nothing + /// was bound. /// /// /// Extensibility point that allows the bound collection to be manipulated or transformed before being @@ -330,7 +332,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders /// /// into which values are copied. /// - /// Collection of values retrieved from value providers. Or null if nothing was bound. + /// Collection of values retrieved from value providers. if nothing was bound. /// protected virtual void CopyToModel(object target, IEnumerable sourceCollection) { diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs index f67df12864..ad13e09a50 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { /// /// An which binds models from the request headers when a model - /// has the binding source / + /// has the binding source . /// public class HeaderModelBinder : IModelBinder { @@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders } var collection = ModelBindingHelper.GetCompatibleCollection(bindingContext, values.Length); - for (int i = 0; i < values.Length; i++) + for (var i = 0; i < values.Length; i++) { collection.Add(values[i]); } @@ -88,4 +88,4 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders return collection; } } -} \ No newline at end of file +} diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs index d46fda50b5..dd4a039c6e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerBinderDelegateProviderTest.cs @@ -871,14 +871,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal { nameof(TestController.NullCollectionProperty), new List { "hello", "world" } }, { nameof(TestController.StringProperty), "Hello" }, }; - var expectedPropertyValues = new Dictionary - { - { nameof(TestController.ArrayProperty), new string[] { "goodbye" } }, - { nameof(TestController.CollectionProperty), new List { "hello", "world" } }, - { nameof(TestController.NonCollectionProperty), new Person { Name = "Ginger" } }, - { nameof(TestController.NullCollectionProperty), null }, - { nameof(TestController.StringProperty), "Hello" }, - }; var actionDescriptor = GetActionDescriptor(); foreach (var keyValuePair in boundPropertyTypes)