AutofacWebApiDependencyResolver usage - asp.net-web-api

What is the usage of the AutofacWebApiDependencyResolver?
I set it like this:
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
But how can I access it in my ApiControllers?
DependencyResolver.Current is not the AutofacWebApiDependencyResolver, its the MVC version.
.Current is available under AutofacDependencyResolver but not under AutofacWebApiDependencyResolver. How can I access the web api version in the web api?

As you showed yourself... use GlobalConfiguration.Configuration.DependencyResolver to access this resolver, same way as you did when you set it initially (it's a static object can be accessed from anywhere in Web API).
Or, use the request dependency scope - wherever you have access to current request (i.e. in MessageHandler):
var myservice = request.GetDependencyScope().GetService(typeof(IMyService)) as IMyService
this will resolve IMyService using the currently set AutofacWebApiDependencyResolver

Try the straightforward way: this.Configuration.DependencyResolver, where this is an ApiController instance.

Related

How to reload appsettings.json at runtime each time it changes in .NET core 1.1 console application?

I attempted to reproduce the method described in this great article by Andrew Lock. However, I am unable to get this running in a .NET core 1.1 console application. When the appsettings.json file is changed and saved, the changes are not reflected in the application without restarting it.
There are multiple files involved, so I created the smallest example I could come up on github. I also provided details in the README.MD file on github.
Any help in resolving this would be most appreciated. Please keep in mind I am new to .NET core, and not an experienced developer. And this is my first question on stackoverflow... Thanks in advance!
The key thing to understand is scope.
There are three scopes in ASP.NET Core - transient, scoped, and singleton. IOptionsSnapshot is configured as a scoped service.
In ASP.NET Core, a scope is started for every request, so every request, you would get a new instance of IOptionsSnapshot, with updated configuration values.
In the example you provided, you are creating an IServiceProvider, and are fetching an instance of IMyService directly from the top level provider:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
var service = serviceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
Essentially, you're always using the same scope for every request to the service provider, so you're always getting the same instance of IOptionsSnapshot. Effectively, if you never create a new scope, all of your scoped services become singletons!
The way to fix this is to create a new scope each time you fetch the service:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
}
This also becomes important if you're doing things like creating an EF Core DbContext outside the context of a request in ASP.NET Core app (or in a console app). Always create a new scope before accessing services from the service provider!
P.S. I've created a pull request to fix your sample :)

Autofac WebApi integration not working with MultiTenant Container

I am quite sure I am missing a very basic and simple thing here.
I am using Autofac and it's multitenant container as below
var builder = new ContainerBuilder();
// Registratino of modules here
var container = builder.Build();
var tenantStrategy = new AppSettingsTenantIdentifier(appSettings);
var mtc = new MultitenantContainer(tenantStrategy, container);
//Registration of tenant specific modules here
var resolver = new AutofacWebApiDependencyResolver(mtc);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
This is called from Application_Start. After above is called, I try to resolved one of the registered classes as below
var webApiConfig = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (WebApiConfig)) as WebApiConfig;
One of the dependencies on this class is registered as InstancePerAPiRequest. At this point I get following error.
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
I am not sure how can I fix this. I Know that I can create a new lifetime scope with tag AutofacWebRequest and then resolve using that lifetime scope but that does not look right to me.
If you register something as InstancePerRequest or InstancePerApiRequest then you can't resolve it outside of a request.
If you need to resolve a dependency outside of a request lifetime (outside an actual API request), choose a different lifetime for it. InstancePerLifetimeScope is very close to InstancePerApiRequest and will work on a per-request basis, too.
But be careful: If you resolve something outside a request from the container and it is IDisposable then the object will stick around for the lifetime of the application because Autofac will hold onto it and try to dispose it for you. If you're unaware of the behavior, this can be a slow memory leak. You can read more about that on the Autofac wiki.

MVC Web API not working with Autofac Integration

I used the MVC integration from autofac like this:
...
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
But now I want to recreate the solution with the new Web Api RTM.
And I want to use the new AutofacWebApiDependencyResolver class.
But if I do this with AutofacWebApiDependencyResolver i got this error:
The type Autofac.Integration.WebApi.AutofacWebApiDependencyResolver
does not appear to implement
Microsoft.Practices.ServiceLocation.IServiceLocator.
I read that i have to do this now for setting the resolver:
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
But if I set it with '=', it is not set. Its still the DefaultResolver...
If I use the MVC AutofacDependencyResolver class again, it works.
Are were still problems with autofac and web api rtm? (the current integration is RC version)
ASP.Net Wep.API and ASP.NET MVC uses two different IDependencyResolver (because they designed the Wep.API to not depend on ASP.NET MVC) so you need to setup both:
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(container);
So the AutofacDependencyResolver is needed to inject decencies to regular MVC Controller derived controllers.
And the AutofacWebApiDependencyResolver is needed to inject dependencies to the Web.API ApiController derived controllers.
And don't forget to register your Api controllers in your container builder with the call (it differs from usual builder.RegisterControllers method):
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
Following is a very good example
Using Autofac with Web Api

ASP .Net 4 Web Api RC + Autofac manual resolving

I'm trying to use depedency resolver inside a Web Api method. This worked fine and works fine with classic ASP.NET MVC with the DepedencyResolver.GetService()
But I can't get this to work inside WepApi methods.
My registration register all instances as InstancePerApiRequest and if I add any of all the types I have registred in my bootstrapper on the constructor of my WebAPiConroller thay inject fine but not anymore when calling them inside.
Like this in my say Get Method
var userRepository = (IUserRepositoryu)GlobalConfiguration
.Configuration.DependencyResolver.GetService(typeof(IUserRepository));
I got the no scope WebRequest error. The strange thing is that it worked fine in Beta before they change it all to the GlobalConfiguration.
So my question is, how can I activate my Autofac registered assemblies in the lifetime scope of my webAPi as before?
My error:
"No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself."
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.DependencyResolver = resolver;
In Web API the global dependency resolver is used to access global instances. Per-request services come from a dependency scope that Web API creates to handle the request. I'm not sure that there is any way in Web API to access the current dependency scope - it would be interesting to know.
The best option here is to just use dependency injection rather than calling the resolver directly like this. Which part of your code needs to make this call?
AutoFac has integration with ASP.NET WebAPI consider to use it.
Also dependecy resolver for WebAPi is slightly different to ASP.NET MVC, so make shure, that you have implemented resolver suitable for WebAPI and added it to WebAPI configuration.
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
As the error indicated, you must always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime. The correct way is getting the dependency from current web api request:
// Get the request lifetime scope so you can resolve services.
var requestScope = Request.GetDependencyScope();
// Resolve the service you want to use.
var userRepository = requestScope.GetService(typeof(IUserRepository)) as IUserRepository;
See more from Autofac offical documentations:
http://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons

How to enable Dependency Injection for ServiceRoute in MVC3 and WCF Web API

I am creating a MVC3 website that will expose a REST API using WCF Web API.
To register routes to the REST API I add code to the Global.asax similar to the code below.
routes.MapServiceRoute<RelationsService>("relations");
This works well enough but i need to use a DI approach to inject the dependencies that the Service depends on.
As you can see in the code above the MVC framework is creating the instance of the RelationsService but this should be done by the DI container.
Does anyone know how to configure MVC3 so that my own DI container is used for creating the instances of the Services?
You have to extend your current service registration call with an IHttpHostConfigurationBuilder that has been created with an IResourceFactory.
var configurationBuilder = HttpHostConfiguration.Create()
.SetResourceFactory(new ResourceFactory());
routes.MapServiceRoute<RelationsService>("relations", configurationBuilder);
Then if you for instance use StructureMap as preferred IoC/DI tool you can just ask for the service in the GetInstance method.
public class ResourceFactory : IResourceFactory
{
public object GetInstance(Type serviceType, InstanceContext instanceContext, HttpRequestMessage request)
{
return ObjectFactory.GetInstance(serviceType);
}
}

Resources