I am trying to understand the UserManagerFactory middleware explained here per request lifetime management for usermanager.
I created this class which I am calling from the Startup Configuration method
public class CustomUserManagerProvider
{
public static CustomUserStore<CustomUser> CreateCustomUserStore()
{
return new CustomUserStore<CustomUser>(/*Need to inject dependencies here*/);
}
public static CustomUserManager CreateCustomUserManager(IdentityFactoryOptions<CustomUserManager> options,
IOwinContext context)
{
return new CustomUserManager(context.Get<CustomUserStore<CustomUser>>());
}
}
And the Startup Configuration
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext(CustomUserManagerProvider.CreateCustomUserStore);
app.CreatePerOwinContext<IngramUserManager>(CustomUserManagerProvider.CreateCustomUserManager);
////....Other things
}
Now, My CustomUserStore has some dependencies which I want to inject in the constructor.
The composition root of the IOC container knows how to resolve these dependencies.
How do I make the CustomUserManagerProvider DI container aware(If that makes sense)...
Although this works
public static CustomUserStore<CustomUser> CreateCustomUserStore()
{
var dependency = DependencyResolver.Current.GetService<ISomeDependency>();
return new CustomUserStore<CustomUser>(dependency);
}
But, I was trying to avoid the service locator (anti)pattern. Is this my only option, Is this even right??
I am using Ninject.
Cant I just create a UserManager in requestScope in the composition root and inject into the controllers, wont that be the same thing?
In a web app, is CreatePerOwinContext same as creating InRequestScope?
Yes, you can inject the UserManager into your controllers a different way if you like, there's nothing that requires using the CreatePerOwinContext/IdentityFactoryMiddleware.
Related
In Azure Functions (v3 on NetCore3.1) using SimpleInjector 5.3, I've followed the guidance here using IHttpClientFactory instead of a typed client that depends on a MS DI-constructed HttpClient, but SimpleInjector can't resolve the IHttpClientFactory either.
public class FooClient
{
private IHttpClientFactory _clientFactory;
private FooClientConfig _config;
public FooClient(IHttpClientFactory clientFactory, FooClientConfig config)
{
_clientFactory = clientFactory;
_config = config;
}
}
public class Startup : FunctionsStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient();
var container = new Container();
container.RegisterInstance<FooClientConfig>(new FooClientConfig() { ApiKey = Configuration.GetValue<string>("FooApiKey") });
container.Register<FooClient>();
services.AddSimpleInjector(container);
}
}
public class FooCommandHandler
{
private readonly FooClient _fooClient;
public FooCommandHandler (FooClient client)
{
_fooClient = fooClient;
}
}
I then use the container to activate a Command/Query mediator but the container can't find an IHttpClientFactory to use for the FooClient.
SimpleInjector.ActivationException: 'The configuration is invalid. Creating the instance for type FooClient failed. The constructor of type FooClient contains the parameter with name 'clientFactory' and type IHttpClientFactory, but IHttpClientFactory is not registered. For IHttpClientFactory to be resolved, it must be registered in the container. Verification was triggered because Container.Options.EnableAutoVerification was enabled. To prevent the container from being verified on first resolve, set Container.Options.EnableAutoVerification to false.'
I guess my question is, where am I supposed to setup the Auto-cross-wiring for simpleinjector? I thought the call to services.AddSimpleInjector(container); would make the MS DI registered IHttpClientFactory available to the container and thus to the registrations therein.
Following the integration guide that Steven has put together over at the SimpleInjector docs VERY CAREFULLY, and using IHttpClientFactory instead of any typed clients I was finally able to get this to work - it is not pretty though.
I suggest that if you're using anything other than the Http factory pattern in the old Azure Functions ecosystem (non-isolated) you'll be fine. It's the cross-wiring of certain services like HttpClient under the hood that makes this a total mess. Hope this helps anyone else facing the same issue.
I have implemented an adapter that implement IServiceProvider and returned it from the ConfigureServices method in the Startup. class:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var kernel = new StandardKernel();
var container = new NinjectComponentContainer(kernel);
// ...
return ServiceProviderFactory.Create(container, services);
}
However, my implementation doesn't seem to be used everywhere. I even tried to override the IHttpContextAccessor to return a modified HttpContext:
public HttpContext HttpContext {
get
{
var result = _httpContextAccessor.HttpContext;
result.RequestServices = _serviceProvider;
return result;
}
set => _httpContextAccessor.HttpContext = value;
}
To test whether I could get to my implementation I used a filter in order to see what the HttpContext.RequestServices would return:
public class AuthorizationTestAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var service = context.HttpContext.RequestServices.GetService(typeof(IAccessConfiguration));
}
}
The type returned by context.HttpContext.RequestServices is:
My main issue was trying to get registered components resolved in the constructor of a filter but it always seems to fail saying the component is not registered. However it does seem to work when using the TypeFilter attribute:
[TypeFilter(typeof(RequiresSessionAttribute))]
However, my attribute does inherit from TypeFilter:
public class RequiresSessionAttribute : TypeFilterAttribute
{
public RequiresSessionAttribute() : base(typeof(RequiresSession))
{
Arguments = new object[] { };
}
private class RequiresSession : IAuthorizationFilter
{
private readonly IAccessConfiguration _configuration;
private readonly IDatabaseContextFactory _databaseContextFactory;
private readonly ISessionQuery _sessionQuery;
public RequiresSession(IAccessConfiguration configuration,
IDatabaseContextFactory databaseContextFactory, ISessionQuery sessionQuery)
{
Guard.AgainstNull(configuration, nameof(configuration));
Guard.AgainstNull(databaseContextFactory, nameof(databaseContextFactory));
Guard.AgainstNull(sessionQuery, nameof(sessionQuery));
_configuration = configuration;
_databaseContextFactory = databaseContextFactory;
_sessionQuery = sessionQuery;
}
I did come across this question but there is no definitive answer.
Any ideas on how to correctly provider a custom implementation of the IServiceProvider interface that will be used throughout the solution?
Even though Microsoft states that it is possible to replace the built-in container it appears as though it is not quite this simple, or even possible.
As stated by Steven in his very first comment, if you choose to use your container of choice, you should run them side-by-side.
The guidance from Microsoft suggests changing the ConfigureServices in the Startup class from this:
public void ConfigureServices(IServiceCollection services)
{
// registrations into services
}
to the following:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var container = new YourContainer(); // Castle, Ninject, etc.
// registrations into container
return new YourContainerAdapter(container);
}
However, there are a number of issues with this since there are already framework registrations in services that we do not necessarily know how to re-register in our own container. Well, there is a descriptor so if our container supports all the various methods then it is actually possible to re-register all the components. The various DI containers have different mechanisms when it comes to registration and service resolution. Some of them have a very hard distinction between the two making it quite tricky at times to accommodate a "common" solution.
My initial idea was to provide an adapter that accepts both my own container as well as the services collection from which I would then get the built-in service provider by calling services.BuildServiceProvider(). In this way I could attempt to resolve from the built-in provider and then, if the resolving bit failed, attempt to resolve from my own container. However, it turns out that the .net core implementation does in fact not use the returned IServiceProvder instance.
The only way I could get this to work was to wire up my own container and use it to resolve my controllers. That could be done by providing an implementation of the IControllerActivator interface.
In this particular implementation I was fiddling with Ninject although I typically prefer Castle but the same applies to any DI container:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IKernel>(new StandardKernel());
services.AddSingleton<IControllerActivator, ControllerActivator>();
}
public class ControllerActivator : IControllerActivator
{
private readonly IKernel _kernel;
public ControllerActivator(IKernel kernel)
{
Guard.AgainstNull(kernel, nameof(kernel));
_kernel = kernel;
}
public object Create(ControllerContext context)
{
return _kernel.Get(context.ActionDescriptor.ControllerTypeInfo.AsType());
}
public void Release(ControllerContext context, object controller)
{
_kernel.Release(controller);
}
}
In order to register the controller types I did my DI wiring in the Configure method since I have access to the IApplicationBuilder which can be used to get to the controller types:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
{
var kernel = app.ApplicationServices.GetService<IKernel>();
// kernel registrations
var applicationPartManager = app.ApplicationServices.GetRequiredService<ApplicationPartManager>();
var controllerFeature = new ControllerFeature();
applicationPartManager.PopulateFeature(controllerFeature);
foreach (var type in controllerFeature.Controllers.Select(t => t.AsType()))
{
kernel.Bind(type).ToSelf().InTransientScope();
}
applicationLifetime.ApplicationStopping.Register(OnShutdown);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(
options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()
);
app.UseMvc();
}
This worked swimmingly for the controllers but resolving "filters" was still a problem given that they use the IFilterFactory on the filter itself to implement a factory method:
public IFilterMetadata CreateInstance (IServiceProvider serviceProvider);
Here we can see that the IServiceProvider implementation is provided in order to resolve any depedencies. This applies when using the TypeFilterAttribute or when defining new filters that inherit from TypeFilterAttribute as I have in my question.
This mechanism is actually a very good example of the difference between "Inversion of Control" and "Dependency Injection". The control lies with the framework (inversion) and we have to provide the relevant implementations. The only issue here is that we are not able to hook in properly since our provided IServiceProvider instance is not passed to the CreateInstance method which then results in a failure when attempting to create an instance of the filter. There are going to be a number of ways to fix this design but we'll leave that to Microsoft.
In order to get my filters working I decided to go the "cross-wiring" route as alluded to by Steven by simply registering the depedencies required by my filters in the services collection also:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IKernel>(new StandardKernel());
services.AddSingleton<IControllerActivator, ControllerActivator>();
services.AddSingleton<IDatabaseContextFactory, DatabaseContextFactory>();
services.AddSingleton<IDatabaseGateway, DatabaseGateway>();
services.AddSingleton<IDatabaseContextCache, ContextDatabaseContextCache>();
// and so on
}
Since I do not have many dependencies in my filter it works out OK. This does mean that we have "duplicate" registrations that we need to be careful of depending on how the instances are used.
I guess another option may be to forego your DI container of choice and use only the built-in container.
How can I use Castle Windsor as an IOC instead of the default .net core IOC container?
I have built a service resolver that depends on WindsorContainer to resolve services.
Something like:
public class ServiceResolver
{
private static WindsorContainer container;
public ServiceResolver()
{
container = new WindsorContainer();
// a method to register components in container
RegisterComponents(container);
}
public IList<T> ResolveAll<T>()
{
return container.ResolveAll<T>().ToList();
}
}
Can not figure out how to let my .net core 2 web API use this resolver as a replacement for IServiceCollection.
For others Reference In addition to the solution Nkosi provided.
There is a nuget package called Castle.Windsor.MsDependencyInjection that will provide you with the following method:
WindsorRegistrationHelper.CreateServiceProvider(WindsorContainer,IServiceCollection);
Which's returned type is IServiceProvider and you will not need to create you own wrapper.
So the solution will be like:
public class ServiceResolver{
private static WindsorContainer container;
private static IServiceProvider serviceProvider;
public ServiceResolver(IServiceCollection services) {
container = new WindsorContainer();
//Register your components in container
//then
serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(container, services);
}
public IServiceProvider GetServiceProvider() {
return serviceProvider;
}
}
and in Startup...
public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddMvc();
// Add other framework services
// Add custom provider
var container = new ServiceResolver(services).GetServiceProvider();
return container;
}
For .net core, which centers DI around the IServiceProvider, you would need to create you own wrapper
Reference : Introduction to Dependency Injection in ASP.NET Core: Replacing the default services container
public class ServiceResolver : IServiceProvider {
private static WindsorContainer container;
public ServiceResolver(IServiceCollection services) {
container = new WindsorContainer();
// a method to register components in container
RegisterComponents(container, services);
}
public object GetService(Type serviceType) {
return container.Resolve(serviceType);
}
//...
}
and then configure the container in ConfigureServices and return an IServiceProvider:
When using a third-party DI container, you must change ConfigureServices so that it returns IServiceProvider instead of void.
public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddMvc();
// Add other framework services
// Add custom provider
var container = new ServiceResolver(services);
return container;
}
At runtime, your container will be used to resolve types and inject dependencies.
There is an official Castle Windsor support for ASP.NET Core which has been released as version 5 (get it from nuget Castle.Windsor, Castle.Facilities.AspNetCore). The documentation how to use it is here.
More info in the related issues here and here
I wanted to add that answer Yahya Hussein offers works for me, however I had to adjust my scope to LifestyleCustome<MsScopedLifestyleManager>() on each dependency I registered.
This may be second nature to some but it took me a minute to figure out.
I have a web api 2 project and I am using Asp.net Identity and Entity framework.
I have discovered that when I change the password, the old one still works but the new one give me error (invalid grant).
I am sure the change password works correctly... Infact in the database the value of the (hashed) password changes correctly.
UPDATE
I have understood why. The authorizationServerProvider (or the user manager I use inside it) is not instanciated per http request. It seems it is a singleton. The problem is that it is instanciated on startup and stop, so it's like it continue to use data of the first login, that are cached (by Entity framework).
Here how I configure my authorizationServerProvider class:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
OAuthAuthorizationServerOptions oauthServerOptions = new OAuthAuthorizationServerOptions
{
//...,
Provider = new TokenBasedAuthorizationServerProvider(),
RefreshTokenProvider = new RefreshTokenProvider()
};
app.UseOAuthAuthorizationServer(oauthServerOptions);
}
How can avoid the login use the cached data?
Thank you
You can try to:
Disable Tracking using AsNoTracking()
Throw away the DbContext and create a new one
Call GetDatabaseValues() to get updated values for single entity
I had the same problem with UseOAuthAuthorizationServer and DI. Last time I faced with this when using Autofac but this is relevant to other DI frameworks. The problem is we have static instance of OAuthAuthorizationServerProvider stored by middleware so no DI involved.
My solution was to get dependencies in OAuthAuthorizationServerProvider in each methods like this:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var scope = context.OwinContext.GetAutofacLifetimeScope();
var userManager = scope.Resolve<ApplicationUserManager>();
.........
}
My container initialization:
public static IContainer Configure(IAppBuilder appBuilder, HttpConfiguration config)
{
var containerBuilder = new ContainerBuilder();
.... registrations here ....
var container = containerBuilder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
appBuilder.UseAutofacMiddleware(container);
appBuilder.UseAutofacWebApi(config);
return container;
}
You can do something like this using other DI containers as well.
With some presumptions from how AutoFac works , i couldn't get my code working in my ASP.NET 5 app.I have integrated AutoFac as DI framework into my ASP.NET 5 app and everything works fine, and dependencies which i register before first call to Build method gets injected fine but when i try to register Modules from other assemblies referenced by main assembly i can't inject theme in controller anymore.
this is what i have tried:
ContainerBuilder builder = new ContainerBuilder();
builder.Register<MyService>().As<IMyService>();
builder.Build();
and after that i've create and registered a Module :
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<SomeService>()
.As<ISomeService>()
.SingleInstance();
}
}
and within a manager class by injecting ILifetimeScope :
public class ManagerClass(){
private readonly ILifetimeScope _lifetimeScope;
public ManagerClass(ILifetimeScope lifetimeScope){
_lifetimeScope = lifetimeScope;
}
public void RegisterModules(){
_lifetimeScope.BeginLifetimeScope(builder =>
{
builder.RegisterAssemblyModules(blueprint.Assemblies.Select(b=>b.Assembly).ToArray());
});
}
}
i put a breakpoint on Load method of MyModule class and it gets hit, but when i try to inject ISomeService (registered by MyModule) i get ComponentNotRegisteredException exception.
This isn't normally how dependency injection is configured. You should configure your dependencies once on startup. Maybe a factory pattern is a better solution in this case?
If you really want that to work though, you will need a reference to the current IContainer and update it