OWIN Service resolution Using Autofac - dependency-injection

I have an WebApi application using OWIN and Autofac. Although controllers and parameters get resolved correctly, I would like to be able to use OwinContext.Get<type> to resolve types registered with Autofac. Is that posible?
Already setapp.UseAutofacMiddleware(container); and config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
By example, I registered builder.Register<IAppConfiguration>(c => new AppConfig()); and I'd like to resolve it using owinContext.Get<IAppConfiguration>().

There is no way to get OwinContext.Get<T> to resolve things from Autofac. If you dive into Microsoft.Owin.OwinContext.Get in Reflector, you'll see it's backed entirely by a dictionary of things you register with an environment. It's not dynamic and there's no way (without creating your own IOwinContext implementation) to get it to resolve things either out of the dictionary or out of dependency resolution.
If you are in a DelegatingHandler or an ApiController you will have a reference to the current HttpRequestMessage. Use message.GetDependencyScope() to get the current request-level dependency scope to resolve services.
public HttpResponseMessage SomeControllerAction()
{
var service = this.Request.GetDependencyScope().GetService(typeof(Service));
}
If you have access to the HttpConfiguration then you can use the HttpConfiguration.DependencyResolver to resolve things. Note that resolver will not have per-request dependencies available. Web API tracks request dependency scope with the inbound HttpRequestMessage so be aware of that limitation. There is an FAQ about per-request lifetime scope that can help you through that.
If you're in a place where there's only an IOwinContext, you may need to make use of a package like CommonServiceLocator and the associated Autofac.Extras.CommonServiceLocator. There really isn't a way to get a reference to the current HttpConfiguration or global container just from an IOwinContext. Again, if you go this route, you won't have per-request dependencies available, so be aware.

The IOwinContext.Get uses the Environment dictionary, resolving objects registered directly with Owin, it does not take into account Autofac container.
I managed to do it by accessing the Autofac OwinLifetimeScope in the Environment property and using the scope to resolve the service.
You can access the LifetimeScope using this code
var scope=OwinContext.Get<Autofac.Core.Lifetime.LifetimeScope>("autofac:OwinLifetimeScope");
and then
scope.GetService(type)
You should check for nulls and write it in a better way, as Extension method maybe.

If you have WebAPI in your project, you can simulate a http request like this
var dependencyScope = new AutofacWebApiDependencyScope(owinContext.GetAutofacLifetimeScope());
var myService = dependencyScope.GetService(typeof(MyService));

Related

Dependency Injection for AzureFunction ServiceBus based on message information

I am working on AzureFunction ServiceBus v3 which handle multi-tenant message. In message I will have TenantId and I will need to register DependencyInjection per message base on this TenantId.
What I tried so far:
At StartUp, I stored the IServiceCollection as static variable
Retrieve the TenantId from the serialized message in Function'd Run method
Update IServiceCollection based on above TenantId and retrieve the Service
_serviceCollection.AddTransient<ITenantIdResolver>(ctx => { return new CompanyResolver{TenantId=tenantId}; }); var service = _serviceCollection.BuildServiceProvider().GetService<T>();
But it throw exception: Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IEnvironment' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Configuration.ScriptHostOptionsSetup' I do some research and look like it was because I used IHttpClientFactory.
How can I fix this?
Or even better if there is a way to retrieve the message in StartUp, so I can inject the tenantId properly? Like
serviceCollection.AddTransient<ITenantIdResolver>(ctx => { var tenantId = GetServicebusMessage().TenantId; return new CompanyResolver { TenantId=tenantId }; }
I think that would be the wrong order of things. Dependency injection should be setup before the message is being processed.
A resolver could be a solution. Register the resolver with the dependency injection container, and let the function be dependent on the resolver. Based on the message you get the right instance from the resolver. In this article it is explained better under "IoC Container Registration #3 – Resolver + Factory Method Pattern": https://techcommunity.microsoft.com/t5/apps-on-azure/dependency-injection-on-azure-functions-5-ways-selecting/ba-p/1502394
According to Dependency injection for azure functions, it's not possible to use the services at an early stage.
My suggestion is to change the architecture to "Durable Orchestrations" so you call an ActivityTrigger function from the orchestrator which gets back list of tenants then you fire other ActivityTriggers that will handle them.

Get DataProtectionProvider in MVC 5 for dependecy injection correctly

When trying to create a DataProtectionProvider manually I have stumbled upon the Microsoft documenation to DpapiDataProtectionProvider which says:
Used to provide the data protection services that are derived from the
Data Protection API. It is the best choice of data protection when you
application is not hosted by ASP.NET and all processes are running as
the same domain identity.
A question suddenly arises: What is the best choice when your application IS hosted by ASP.NET?
Searching further, it seems the best choice is to obtain the DataProtectionProvider from OWIN. That can be done in Startup configuration, where you have IAppBuilder and using AppBuilderExtensions located in Microsoft.Owin.Security.DataProtection namespace you can call app.GetDataProtectionProvider().
So far, I am quite satisfied. However, now you want to inject the DataProtectionProvider in a constructor of your class (e.g. a UserManager). I have seen one suggestion where you store the DataProtectionProvider in a static property and then use it where you need, but that seems like a rather wrong solution.
I think a solution similar to the following piece of code would be appropriate (using ninject container):
kernel.Bind<IDataProtectionProvider>()
// beware, method .GetDataProtectionProvider() is fictional
.ToMethod(c => HttpContext.Current.GetOwinContext().GetDataProtectionProvider())
.InRequestScope();
There is a walkthrough that tells you how to register the DataProtectionProvider with Autofac.
builder.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).InstancePerRequest();
You can also achieve this with Unity with the following line:
container.RegisterType<IDataProtectionProvider>(new InjectionFactory(c => app.GetDataProtectionProvider()));
Where container is
var container = new UnityContainer();
This will allow you to use the DataProtectionProvider in the constructor as follows.
public ApplicationUserManager(IUserStore<ApplicationUser> store, IIdentityMessageService emailService, IDataProtectionProvider dataProtectionProvider)
I prefer this approach over the approach mentioned on this blog post here https://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/, simply because it allows you to have the classes that use the DataProtectionProvider in separate libraries if you would like and it is much cleaner.

Configure injected services with information available in runtime

I've been trying to modify injected services with values available from authenticated users.
Using the built-in DI container, I added the required service with Scoped lifetime.
services.AddScoped<ITodoRepository, TodoRepository>();
Then registered a custom middleware between authorization and MVC middlewares to modify the repository with user specific information.
// Configure authorization middleware
app.Use(async (context, next) =>
{
var todoRepository = context.ApplicationServices.GetRequiredService<ITodoRepository>();
todoRepository.UserStoreId = context.User.GetUserStoreId();
await next.Invoke();
});
// Configure MVC middleware
When the program execute a request, the injected repository within my controller does not presist the saved value.
Am i doing something wrong?
From my understanding, scoped objects are saved within request.
Also, is there another way to achieve this?
You can create your own service, i.e. IAuthenticatedUserService/AutheticatedUserService.
Into it, you inject IHttpContextAccessor.
public interface IAuthenticatedUserService
{
ClaimsPrincipal User { get; }
}
Then you inject the IAuthenticatedUserService into your repository, where you can access the logged-in user.
Of course you could also directly inject IHttpContextAccessor into your repository and access httpContextAccessor.HttpContext.User within it, but since repositories are usually defined in their own assembly, you'd also need to reference the Microsoft.AspNetCore.Http.Abstractions package from it which would cause a tight(er) coupling.
But if you don't mind this kind of coupling, just inject the IHttpContextAccessor into your repository, they are supposed to be scoped (=per request) or transient anyways.
P.S. don't forget the Dependency Injection/Inversion of Control mantra: "Don't call us, we call you". You have attempted to call "us" (the repository) to set a value.
Am i doing something wrong? From my understanding, scoped objects are saved within request.
I was able to fix the issue by replacing
context.ApplicationServices.GetRequiredService<ITodoRepository>();
with
context.RequestServices.GetRequiredService<ITodoRepository>();

Unity Dependency Injection for WCF services

Can someone direct me to a good example of Unity Dependency Injection for WCF services?
Any blog or msdn article will also help.
This answer gives an example on how to enable DI in WCF with Castle Windsor.
Just replace the IWindsorContainer with an IUnityContainer in the example and you should be all set, although you may also want to change the class names from WindsorXyz to UnityXyz :)
To inject dependencies into WCF services I had to implement a service host factory.
I have found a step-by-step tutorial here.
Basically you have to:
Implement an IInstanceProvider to create services using the container
Implement an IServiceBehavior to set the instance provider in the endpoint dispatcher
Extend ServiceHost to add the new service behavior
Extend ServiceHostFactory to create the new service host
I'm about to give a try to Unity.Wcf library (https://github.com/ViceIce/unity.wcf), at first sight looks pretty good. I've read in this article this:
If you are hosting your WCF service within a Windows Service using a ServiceHost, replace the ServiceHost instance with the custom Unity.Wcf.UnityServiceHost. You will find that the UnityServiceHost takes in a Unity container as its first parameter but is otherwise identical to the default ServiceHost.
As it is my case I'm going to do this...
class Program
{
static void Main(string[] args)
{
// 1st Initialize the Host (Configures Container and Factories)
ServiceHostController.Initialize();
// 2nd Create a URI to serve as the base address.
var baseAddress = new Uri("http://localhost:54321/BlaBlaBla/");
// 3rd Create a UnityServiceHost instance
var myService = new UnityServiceHost(ServiceHostController.UnityContainer, typeof(MyService), baseAddress);
try
{ //etcetera...
And it worked for me, I still have to refactor some things and add features and methods but the starting point works like a charm.
I hope it helps.

How do I make sure that there is one NHibernate ISession per request using Autofac?

I have the following code in an Autofac Module that is used in my Application_Start method:
builder.Register(c => new Configuration().Configure().BuildSessionFactory())
.SingletonScoped();
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
.HttpRequestScoped();
builder.Register<NHibernateSomethingRepository>().As<ISomethingRepository>();
The constructor for the repository takes an ISession as argument. But I end up with one session for the whole application, even though I explicitly asked for it to be HttpRequestScoped.
I have configured the ContainerDisposal HTTP module.
According to the documentation you have to create a nested container, but I'm letting Autofac autowire the dependencies.
What should I do?
Thanks!
I found the problem, so I will answer my own question.
I registered my repository with the default scope, which in Autofac is singleton scope. I should have done this:
builder.Register<NHibernateSomethingRepository>()
.As<ISomethingRepository>()
.HttpRequestScoped;

Resources