This change makes RouteValueDictionary a full IDictionary implementation
instead of a subclass of Dictionary.
Followed the patterns used in the old implementation, namely preserving
the struct-returning behavior of Keys/Values/GetEnumerator.
This is useful for a variety of interesting scenarios in link generation
where a default value doesn't appear in the route template as a parameter.
This can be used to implement the desired behavior for areas - where the
'area' key is sticky.
This change adds tests and makes the behavior consistent with legacy MVC
as far as what values are visible in constraints.
This is important because it allows constraints to make decisions based on
whether or not a value is present even if it's not in the template. This
is similar to the behavior of WebAPI link generation or Area link
generation in MVC 5 - but without hardcoding.
This is the routing part of these changes, and just the breaking changes
parts.
Follow-ups will add:
- DataTokens
- Tracking the logical stack of routers
Moving out Default Handler and IInlineConstraintResolver from RouteCollection.
These are moved to a new interface IRouteBuilder, (instead of an IInlineConstraintResolver, it takes in an IServiceProvider).
This means all RouteCollectionExtensions are moved to RouteBuilderExtensions.
For link generation to areas, we need to provide the set of values that
the route could potentially provide.
Basically if we know what action we want to reach, we want to know whether
or not a given route could hit that action before giving it the OK to
generate a link.
For instance a route like '{controller}' couldn't hit an action like
'HomeController:DoACoolThing', since it can never provide a value for
'action'. This makes it possible for WebFX to make the right decision
without changing the behavior of any of the routing constructs. This also
has the side-effect of removing a class of order dependencies in routing
that cause bad links to be generated.
We'll need to access the accepted values to do proper link generation, so
separating this process out into 2 parts.
Also moving defaults into the TemplateBinder because they are conceptually
part of the route, not part of the request. I'll do the same for
TemplateMatcher soon, but it's a big change and worth separating.