- #5502
- support thousands separators for `decimal`, `double` and `float`
- add tests demonstrating `SimpleTypeModelBinder` does not support thousands separators for numeric types
- add tests demonstrating use of commas (not thousands separators) with `enum` values
- #6076
- add resources and accessors specifically for the element / parameter cases
- avoid `metadata.GetDisplayName()` where possible
- fill in the `ValidationContext` that `ValidatorObjectAdapter` uses
- e.g. `Validate_NestedComplexType_IValidatableObject_Invalid()` test fails without this
Possible future work:
- improve error message used for `ModelMetadata.IsRequired` elements and parameters
- use something besides the type for `ValidationContext.DisplayName` of elements and parameters
nits:
- trailing whitespace
- use more `out var`
- #5642
- lazy-load `ValidationEntry.Model`
- avoids `Exception`s when moving to a property that will not be validated
nits:
- remove duplicate code in `ValidationVisitor`
- clarify "all properties of" doc comments
- also add missing `<param>` doc in `ViewDataInfo`
- #3918
- precompute size of `StringBuilder` in `ExpressionHelper`
- reduce `string` allocations in `ViewDataEvaluator`
- also get rid of `Enumeration` state machines
- reduce the size of a few objects; use more expression-valued properties
- e.g. don't store `_modelType` in `ModelExplorer`
- add `EmptyArray<TElement>`; make empty arrays consistently `static`
- avoid `string.Split()` in HTML and tag helpers
nits:
- make `ExpressionHelperTest` tests more stringent
- correct `Message` for an `ArgumentNullException`
- remove excess `using`s in classes I touched (but often ended up leaving otherwise unchanged)
- improve doc comments
- remove `ToString()` call on a `string`
- avoid encoding `string.Empty`
- fix test file name
- remove useless variables
- correct spelling
- improve whitespace
- #4988
- preserve whitespace as the setting demands
- correct previous `string.IsNullOrEmpty()` call to match previous `ValueProviderResultExtensions.ConvertTo()` use
- short-circuit other `string`-to-`string` conversions (as `ValueProviderResultExtensions.ConvertTo()` does)
- correct documentation of `ConvertEmptyStringToNull` properties
- add more tests of these scenarios and remove duplicate `BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull()` test
- #4690
- move `ModelBindingMessageProvider` init from `DefaultBindingMetadataProvider` to `DefaultModelMetadata`
- in addition to avoiding error cases, this removes some boilerplate
- add specific errors to `BodyModelBinderProvider`, `CompilerCache`, `CompositeViewEngine`, `ModelBinderFactory`,
and `ObjectResultExecutor`
- `DefaultRazorViewEngineFileProviderAccessor.FileProvider` now a `NullFileProvider` in empty case
This change to ModelBinderFactory makes the caching much more aggressive,
by caching all non-root binders. There's some trickiness here around
making sure we have the right behavior when all providers return null. See
the tests and comments.
I also kept the change I made for a temporary workaround to use a
dictionary rather than a "stack" for cycle breaking. This seems like an
overall improvement in clarity.
- #4652
- previously ignored for top-level models
- `ModelBinderProviderContext.BindingInfo` is now never `null`
- similarly, use type metadata (as well as parameter info) for `ModelBindingContext.BinderModelName`
- previously ignored when overridden in `ControllerArgumentBinder`
This change simplifies a bunch of code and fits more in line with the
current design of model binding.
Now, a model binder only has to do anything if it was successful.
'return' is enough to indicate failure.
We want this change to avoid MVC eagerly reading the form. This is good
for general perf and also for scenarios where you want read the body
yourself (large file uploads).
We DO have scenarios where you want to configure the value providers
per-request or also to change the limits on the value providers (form) so
it's worth keeping these around on the context.
This change renames IPropertyBindingPredicateProvider to
IPropertyFilterProvider. The changes here are mostly renames of
parameters/variables from predicate -> propertyFilter. I did a
find+replace and left the term 'predicate' in some of the docs because it
refers to a predicate in the abstract sense.
This change also simplifies BindAttribute and removes support for type
activation.
This commit introduces application parts as a concept on MVC.
An application part is an abstraction that allows you to expose some
feature or corncern in a way that is decoupled from their underlying source.
Examples of this include types in an assembly, emdeded resources, files on
disk etc.
Application parts are configured during startup by adding or removing them from
the application part manager available as part of IMvcBuilder and IMvcCoreBuilder.
The application part manager provides the ability to populate features from the
list of available application parts by using a list of application feature providers.
Application feature providers are responsible for populating a given feature given a
list of application parts.
Examples of application providers can be a ControllerFeatureProvider
that goes through the list of application parts, sees which one of those parts exposes types,
determines which of those types are controller types, and adds them to a ControllerFeature
that holds a list of all the types that will be considered controllers in the application.
This change no longer suppresses validation for IFormFile and
IFormFileCollection model values. This will allow the use of [Required] on an
IFormFile model, or a custom attribute for validating IFormFileCollection.
These types already have ValidateChildren = false, so we don't recurse
into them.
This change separates model binding into IModelBinderProvider (decides
which binder to use) and IModelBinder (does binding). The
IModelBinderFactory is a new services with coordinates the creation of
model binders.
- #3482
- see new tests; many failed without fixes in the product code
- add support for binding `IFormFileCollection` properties
- make `FormFileModelBinder` / `HeaderModelBinder` collection handling consistent w/ `GenericModelBinder`++
- see also dupe bug #4129 which describes some of the prior inconsistencies
- add checks around creating collections and leaving non-top-level collections `null` (not empty)
- move smarts down to `ModelBindingHelper.GetCompatibleCollection<T>()` (was `ConvertValuesToCollectionType<T>()`)
- add `ModelBindingHelper.CanGetCompatibleCollection()`
- add fallback for cases like `public IEnumerable<T> Property { get; set; } = new T[0];`
- #4193
- allow `Exception`s while activating collections to propagate
- part of #4181
- `CollectionModelBinder` no longer creates an instance to check if it can create an instance
- not a complete fix since it still creates unnecessary intermediate lists
nits:
- correct a few existing test names since nothing is not the same as `ModelBindingResult.Failed()`
- remove a couple of unnecessary `return` statements
- correct stale "optimized" comments
- explicit `(string)`
- unrelated to #3482 except that I discovered the issue while investigating that issue
- tests previously set `BindingDetails.IsReadOnly` for a `Type` and that was ignored
- same for `DictionaryModelBinderTest`
This undoes a behavior change introduced in
7b18d1d3f1.
The intent was to have ClearValidationState do the right thing for a case
where a collection was bound to the empty prefix, and then used again with
TryUpdateModel.
This change was implemented by saying that a key like "[0].Foo" is a match
for the prefix of "Foo". This isn't really right, and it's only
interesting for the ClearValidationState case.
The problem is that we don't know what the keys look like for a
collection. We can assume that they start with [0] but that's not really a
guarantee, it's a guess.
This change fixes the behavior of StartsWithModel, and move the
responsibility for this case back into ClearValidationState.
This change also removes the call to ClearValidationState from
TryUpdateModel. If you need this behavior, then call ClearValidationState
manually. Trying to bind and then re-bind a model object isn't really what
we intend.