- #2992
- use new properties to replace common helper methods
- still a few `Nullable.GetUnderlyingType()` calls
- creating `ModelMetadata` or sites lacking `ModelMetadata` access e.g. `ModelBindingHelper.ConvertTo()`
- Removed TaskHelper and refactored with ClosedGenericMatcher
- Removed TypeHelper
- Moved custom encodings to InputFormatter
- Moved ObjectToDictionary to PropertyHelper
- Removed respective tests and test projects
- cleanup duplicate code now that #2445 is fixed
- update unit tests using old `ModelBindingContext` setups
- fix (just) one integration test where `MutableObjectModelBinder` incorrectly calculated
`isTopLevelObject` and returned a non-`null` model
- undo temporary changes in `BodyModelBinderTests` due to increased reliance on incorrect
`isTopLevelObject` in #2445 fix
nits:
- combine tests that are now duplicates
- beef up coverage of some `MutableObjectModelBinderTest` cases
- remove unused `using`s
- use valid `multipart/form-data` content type; include a `boundary`
- correct expectations of `FormCollection` model binder's operation
- restore tests actually skipped for either of the above reasons
- add more tests with `ModelBindingResult.Model==null` and both `IsModelSet` values
#### Remove test references to Won't Fix bug #2473
- restore #2473 tests; update test expectations
- expect `null` composite results whenever binding fails
#### Restore test skipped due to "#2646"
- that issue does not exist; was likely #2466 or similar fixed bug
#### Rename model binding tests that still mention ReturnsFalse or ReturnsTrue
#### Minor src changes
- remove unused variable and unnecessary nesting in `DefaultControllerActionArgumentBinder`
- remove dangling mention of `[DefaultValue]` in `ComplexModelDtoModelBinder`
#### nits:
- remove empty delegates from some `GetOperationBindingContext` calls; `null` fine
- do some `using` cleanup
- combine two test methods in `KeyValuePairModelBinderTest`
- name a few more arguments
- part 1/2 of #2294
- handle readonly non-`null` collections in relevant binders
- `CollectionModelBinder.CopyToModel()` and `MutableObjectModelBinder.AddToProperty()` methods
- handle read-only controller properties in `DefaultControllerActionArgumentBinder`
- do not copy into arrays e.g. add `CopyToModel()` override in `ArrayModelBinder`
- remove ability to set a private controller property
- confirm `SetMethod.IsPublic` in `DefaultControllerActionArgumentBinder`
- avoid NREs in `GetModel()` overrides
Test handling of readonly collections
- previous tests barely touched this scenario
- also add more tests setting controller properties
nits:
- add missing `[NotNull]` attributes
- add missing doc comments
- consolidate a few `[Fact]`s into `[Theory]`s
- simplify some wrapping; shorten a few lines
- remove dead code in `DefaultControllerActionArgumentBinder` and `ControllerActionArgumentBinderTests`
Consider
public class Person
{
[FromBody]
public Address Address { get; set; }
}
public class Address
{
[Required]
public string Street { get; set; }
public int Zip { get; set; }
}
Request body { "Zip" : 12345 }
In this case the error key would be "prefix.Address.Street" (assuming there is a prefix because of additional metadata/positioning for/of the Person model).
public class Person
{
[Required]
public string Name { get; set; }
}
public void Action([FromBody]Person p)
{
}
Request body { }
In this case the prefix gets ignored and the error key is Name.
Please note this is so that we are compatible with MVC 5.0
public class Person
{
[Required]
public string Name { get; set; }
}
public void Action([FromBody][ModelBinder(Name = "prefix")] Person p)
{
}
public void Action2([FromBody][Bind(Name = "prefix")] Person p)
{
}
Request body { }
In both these cases (Action and Action2) the prefix gets ignored and the error key is Name.
This is a slight improvement from mvc, as in MVC the action parameter would be null.
The followup for this would be to fix#2416 -
This PR ignores the validation assuming that #2416 will address the issues and update the test.
NOTE: previous versions of mvc did not have property binding and hence there is no precedence in this case. For MVC and Web API it was possible to body bind an action parameter which used an empty prefix instead of a parameter name for adding errors to model state (In case of MVC if a custom prefix was provided, it failed binding from body i.e the parameter was null).
This change removes reflection from validator providers, and instead
relies on cached metadata in in the modelmetadata.
In general this means that our MVPs don't need to cache anything, they
just look at the metadata and create what they need.
In the case of data-annotations, we update the model details provider to
add validation attributes to the modelmetadata. This would allow someone
to replace the DataAnnotationsValidatorProvider, but still use the
metadata in these attributes.
The change to the IModelValidatorProvider api (to use a context) is
intended to minimize allocations. Currently each validator provider needs
to return a list so you end up with N+1 lists (N validators + a final list
to compine them all). This change will let us just create the final list
(and a small context object). This is a very very high traffic API so it
seemed worth doing.
There's also some general massaging of namespaces and file locations.
Separates the MMP into two phases:
1). Creation of the ModelMetadata, discovery of properties and attributes
(reflection) is part of the MMP
2). Lookup of details based on attributes is now part of another phase,
and has its results cached.
Users can now implements and register an IFooMetadataProvider to customize
a single aspect of metadata (see how data annotations does it).
This also fixes#1503.
Currently all model binders except mutable object binder are independent of validation code. The mutable object binder which needs to do some validation ( for scenarios involving [BindRequired] and [BindNever]).
We would be going with an approach where required validaiton happens in input formatters and model binders.
This is needed as validation for value types can best be done at creation time.
Followup PRs:
Introduce support for skipping validation (and not binding) for a particular property/type etc.
Changes here are all focused around MaxModelErrors on
ModelStateDictionary.
MaxAllowedErrors now defaults to 200 (same as options). This means that
constructing a new ModelStateDictionary with the default constructor will
use this default. There's a new constructor for creating a
MaxAllowedErrors with a non-default value.
The ControllerActionArgumentBinder is now responsible for setting the
value from options onto ActionContext.ModelState. This results in better
layering and guarantees the option is respected if someone uses
extensibility to call model binding.
ModelStateDictionary.CanAddErrors is renamed to MaxErrorsReached. We
wanted to change the behavior of this property, but realized that it's
very useful inside the model validation code, so opted to renamed.
There's also a bunch of doc cleanup inside ModelStateDictionary to
simplify things and improve clarity.
This change adds support for our three-valued logic to the default value
handling part of the MutableObjectModelBinder.
The issue is that we want to look up a default value when a 'greedy' model
binder returns true but doesn't find a value.
We also don't want to call the property setter unless there is:
1). A value from model binding OR
2). A default value
This is a new filter stage that surrounds the existing model binding,
action, and result parts of the pipeline. Resource Filters run after
Authorization Filters.
The other major change is to support one of the primary scenarios for
Resource Filters. We want a filter to be able to modify the inputs the
model binding (formatters, model binders, value providers, etc) -- this
means that those changes need to be held on a context object and preserved
so that they can be used in the controller.
So, IActionBindingContextProvider is removed - the ActionBindingContext
will be created by the invoker. For now it will be part of the action
context.
- StyleCop working again (handles C# 6.0 additions) though only locally for me
- disable some new rules:
- ConstFieldNamesMustBeginWithUpperCaseLetter
- InstanceReadonlyElementsMustAppearBeforeInstanceNonReadonlyElements
- StaticReadonlyElementsMustAppearBeforeStaticNonReadonlyElements
- StaticReadonlyFieldsMustBeginWithUpperCaseLetter
- PrefixCallsCorrectly
- correct remaining violations
- lots of long lines for example
- use more `var`; some manual updates since StyleCop doesn't check seemingly-unused blocks
nit: remove new trailing whitespace (was paranoid about adding it w/ fixes)