Looking on different libraries and even Microsoft code I've noticed two different ways of configuring options in code:
in ConfigureServices
it can be done when registering DependencyInjection
:
services.AddMvc(options => { });
or in Configure
app.UseStaticFiles(
new StaticFileOptions
{
ServeUnknownFileTypes = true
});
I tried to find out, which way use for which purpose and still don't know, assuming that creating your own middleware and registering both DI and usage.
Interesting issue you have found.
Looking into the source code i have found the following:
All the middleware registrations are an overload of this UseMiddleware function, which is an overload of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
.
In these overloads you can specify hard your own parameters for the middle-ware. Say you have a few strings in the constructor, the DI container will not be able to resolve this.
If the parameters aren't set though, it does fallback to the IServiceProvider
to resolve the specific type. see extension class: Microsoft.Extensions.Internal.ActivatorUtilities
(inside: Microsoft.AspNetCore.Http.Abstractions.dll
)
As for best practice think about the following (my opinion though):
services.Configure<>()
as here you can specify options from a ConfigSection => appsettings.I think best practise is to: Register Middleware AND its dependencies as singletons in IOC on startup. then resolve it yourself and add it yourself with the method App.Use([yourDelegate])
.
The advantage of this method is it is easilier understandable than use the hidden microsoft code + Microsoft recently published an upgrade to the DI container to check if the scopes of your registrations match properly (and warn you if not).
This tool basically does: it checks if a dependency of a service has a smaller scope then the service itself: say service is scope: Singleton
and the dependency is scope Transient
. this means that if Singleton
is resolved Transient
is also resolved for this singleton and thus not resolved again on next usage of this singleton. (so its a hidden singleton usage).