Skip to content

Restier Dependency Injection Changes in RC6

Robert McLaws edited this page Mar 27, 2021 · 1 revision

Background

Prior to RC1, the MapRestier<TApi>() function combined route mapping and service registration into a single process, which allowed Restier to confirm to OData's per-route DI container design.

Recently, we broke apart DI registration and Route mapping to make the experience feel more like ASP.NET Core. In theory, this was supposed to help break apart Restier core services from the ones specific to a given route, and to ease migration to .NET Core in the future.

But we made a few mistakes in making that jump. Essentially, every time you call HttpConfiguration.MapODataServiceRoute(), the entire OData stack is dumped into a container specific that route. We expected Core services to be registered just once, and per-route services would be isolated to ONLY services that were unique to that route, but that is not the case.

Impact

From RC1 to RC5, when you added multiple APIs to Restier, those APIs were made available on EVERY route, and OData had no idea which API or EdmModel to use. This happened partially because OData's DI architecture does not pass the RouteName a container is being built for when a new Container is requested, so there was no way for us to get the right Services to the right Container at the right time.

Changes in RC6

We have refactored the process to correctly take into account the intent of the original design with a modern execution. We've outlined the changes below:

  • We designed our own OData registration system that allows the container-building process to be Route-aware. This allows the RestierContainerBuilder to return a ServiceProvider built specifically for that Route, which is not polluted with things required for other routes.

    • This is hopefully the first step in proving adjustments to OData's Dependency Injection architecture that will allow it to be much more memory-efficient in complex situations.
  • HttpConfiguration.UseRestier() now passes a RestierContainerBuilder instance instead of an IServiceCollection instance. That process will allow you to add APIs independently, and specify the services required for those APIs individually.

  • Internally, when you call HttpConfiguration.MapRestier(), we will now pass in a new RestierRouteBuilder, which allows you to register multiple Restier Routes, and maps previously-registered Apis and Services to their proper Route.

  • The ModelBuilder will now execute model generation once at startup, to streamline the processing pipeline. You will still be able to update models on the fly, but it will require building custom ModelBuilder that replaces the IEdmModel instance in the DI container on the fly.