im trying to use Autofac and configure an appconfig.json:
private static void RegisterAppSettingsConfiguration(ContainerBuilder builder)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
var module = new ConfigurationModule(config.Build());
builder.RegisterModule(module);
}
Is this all the code to set up the IConfiguration Interface? (after that, a builder.Build() of course).
It doesn't find the object that implements IConfiguration:
Cannot resolve parameter 'Microsoft.Extensions.Configuration.IConfiguration config' of constructor 'Void .ctor(CamTool.Avalonia.GUI.Models.Interfaces.IGUILogger, Microsoft.Extensions.Configuration.IConfiguration)'.
When i change the name of the appsettings.json there is another exception (file not found), so that part works fine i guess.
Do i need to wire up an implementation of an IConfiguration object? I thought it's been doing that behind the scenes.
My other DI stuff works just fine with Autofac.
Thanks
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
builder.RegisterInstance<IConfiguration>(configuration);
This is the solution - i had to directly use the instance of the IConfiguration and link it up by myself
Related
I have an Azure Functions app. I would like my code to be able to access settings configured for the Azure Functions app. I am using Microsoft.Extensions.DependencyInjection for dependency injection.
To access configuration data, I am using this code:
[FunctionName("MyEndpoint")]
public static Task<IActionResult> MyFuncAsync(ExecutionContext context)
{
IConfigurationRoot config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
}
This works great in the function itself. However, I would like to be able to injection IConfigurationRoot into my classes. I can't figure out how set up the dependency injection container so that it will create the IConfigurationRoot class using the execution context injected into the Azure function method. I'd like to be able to create a class like this:
public class MyWorkerClass(IConfigurationRoot config)
{
...
}
I must integrate Oauth with Autofac. But something goes wrong. I think I understand why, but I don't know how to solve it. I let you see my code.
My Autofac Config
{
builder.RegisterType<CustomAuthorizationServerProvider>()
.PropertiesAutowired()
.SingleInstance();
builder.RegisterType<MyBusinessObj>()
.As<IMyBusinessObj>()
.InstancePerRequest()
.PropertiesAutowired();
//IMySessionObj is a prop inside MyBusinessObj
builder.RegisterType<MySessionObj>()
.As<IMySessionObj>()
.InstancePerRequest()
.PropertiesAutowired();
//IMyUnitOfWorkObjis a prop inside MyBusinessObj
builder.RegisterType<MyUnitOfWorkObj>()
.As<IMyUnitOfWorkObj>()
.InstancePerRequest();
...
}
Startup.cs
I have the classic configuration plus the resolution of my authorizationServerProvider.. As you can see, I resolve it in the container... because it is a singleton.
app.UseAutofacMiddleware(_container);
app.UseAutofacWebApi(config);
var oauthServerOptions = new OAuthAuthorizationServerOptions
{
...,
Provider = _container.Resolve<CustomAuthorizationServerProvider>()
};
app.UseOAuthAuthorizationServer(oauthServerOptions);
app.UseWebApi(config);
CustomAuthorizationServerProvider.cs
This is how I have implemented my CustomAuthorizationServerProvider.
public class CustomAuthorizationServerProvider: OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
var autofacLifetimeScope = OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>();
var xxx = myBusinessObj.DoWork();
...
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>();
var xxx = myBusinessObj.DoWork();
...
context.Validated(ticket);
}
}
Here I solve my IMyBusinessObj in a lifetimescope, not in the container. This object is responsible (indirectly) to connect to db, access the session, access the cache and so on... so it cannot be a singleton.
I need it would have a lifetime per request.
So here the problems.. Two problems there are in my configuration.
I have a InstancePerRequest object inside a SingleInstance object. I cannot do that. Troubleshooting Per-Request Dependencies
I effectively cannot have a InstancePerRequest object when I configure oauth in the startup... because in that context does not exist a request yet.
So.. I have understood which are my problems.
Any idea or tips?
Thank you
I was having a very similar issue if not the same. I was able to resolve it by doing the following:
1. Do not resolve IOAuthAuthorizationServerProvider directly from the container. Instead, use IDependencyResolver. In your example:
var oauthServerOptions = new OAuthAuthorizationServerOptions
{
...,
Provider = (IOAuthAuthorizationServerProvider)resolver.GetService(typeof(IOAuthAuthorizationServerProvider)),
};
This requires that you have correctly configured HttpConfiguration.DependencyResolver:
HttpConfiguration config = new HttpConfiguration();
... // Configure unrelated
var builder = new ContainerBuilder();
... // set Autofac registrations
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// THIS is where you configure OAuthAuthorizationServerOptions, using IDependencyResolver to resolve IOAuthorizationServerProvider instead of IContainer
ConfigureAuth(app, config.DependencyResolver);
2. I was using dynamic assembly scanning to configure certain Autofac module registrations. I inadvertently was scanning for classes ending with "Provider" and registering them as RequestPerInstance(). This was a problem for me, as it was re-registering my IOAuthAuthorizationServerProvider as a per-request instance, which is unable to be resolved during Startup() code.
Problem code which I replaced with individual registrations:
builder.RegisterAssemblyTypes(executingAssembly)
.Where(t => t.Name.EndsWith("Provider"))
.AsImplementedInterfaces()
.InstancePerRequest();
3. Check properties of MySessionObj, and see what dependencies Autofac is resolving (if any). Make sure that you are explicitly registering dependencies as InstancePerRequest().
By using OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);, you are resolving dependencies to the "AutoFacWebRequest" lifetime scope, and not the root scope. As a result, my understanding is dependencies resolved to this lifetime scope should be disposed after the request has finished and shouldn't cause future problems with your application.
4. I am not sure what properties are being autowired for your CustomAuthorizationServerProvider object, but assuming you did not post a complete code sample for this class, I would try removing PropertiesAutowired() from it's Autofac registration and inside the object continue to use OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext); to resolve these other properties if possible.
Could you provide specific detail about what the error or error message you are observing is?
I have an existing MVC application that is using Dependency Injection with Ninject. I installed the Ninject.MVC3 nuget package and it creates a class called NinjectWebCommon in my App_Start, which completely isolates the kernel and registers all of my bindings:
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFoo>().To<Foo>();
}
We have a new requirement that we thought SignalR would be able to satisfy, so we installed SignalR 2 nuget package into the project. I created a Hub and did some searching on how to implement Dependency Injection into the project and found an article that suggests creating a SignalRDependencyResolver. http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection
The article has you creating a kernel in the Startup.cs file that is used for registering SignalR in OWIN:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var kernel = new StandardKernel();
var resolver = new NinjectSignalRDependencyResolver(kernel);
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
var config = new HubConfiguration()
{
Resolver = resolver
};
app.MapSignalR(config);
}
}
The problem is that this approach has me creating two different kernels and they seem to have their own set of dependencies that they know how to resolve. If I have a dependency defined in NinjectWebCommon, the Hub doesn't know how to resolve that dependency. Without exposing my kernel in NinjectWebCommon, what is the proper way to add DI into SignalR using the Ninject.MVC3 package?
None of the current answers directly answer your question. Also achieving the result you are after is very straightforward once you know exactly what to do. The "proper" way to do this is to set SignalR's dependency resolver in the CreateKernel method of the NinjectWebCommon class.
Assuming you have created a NinjectSignalRDependencyResolver class as you mention, no other code needs to be added anywhere except for the line highlighted in the code snippet below:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// THIS LINE DOES IT!!! Set our Ninject-based SignalRDependencyResolver as the SignalR resolver
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
Apart from the above, nothing more needs to be done except declaring your bindings in the RegisterServices method of NinjectWebCommon. In your example this would look like:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
}
Except for the NinjectSignalRDependencyResolver class you created, no other code needs to be added. Importanly, the OwinStartup class remains unmodified, as follows:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
The above example achieves the following important outcomes which were what you asked in your question:
You only have a single Ninject Kernel created
The kernel and all binding configurations remain confined to NinjectWebCommon
The default SignalR resolver is your NinjectSignalRDependencyResolver
Dependency Injection into all SignalR hubs is achieved
Hopefully this helps people out.
Have you tried adding the StockTickerHub itself to your kernel?
By default, SignalR uses Activator.CreateInstance to construct Hubs without any constructor arguments. If you want to inject your own dependencies into a Hub, you can do so by registering the Hub with SignalR's dependency resolver.
https://github.com/SignalR/SignalR/blob/2.0.1/src/Microsoft.AspNet.SignalR.Core/Hubs/DefaultHubActivator.cs#L28
If you want to get really creative, you can register your own IHubActivator instead of registering all of Hubs individually.
I go into more detail in how Hubs are created by default in this answer: SignalR with IoC (Castle Windsor) - which lifetime for hubs?
There is a problem with the singleton scope. I don´t know who should get the blame here (Ninject, SignalR, MVC, etc...), but it works if you use ToConstant:
var binding = Bind<IMustBeSingleton>().ToConstant(new MustBeSingleton());
I had the same problem, and I found the solution: SignalR, WebAPI and MVC sharing the same dependency resolver kernel
I shared a complete solution with MVC, WebAPI and SignalR using the same Ninject kernel: https://drive.google.com/file/d/0B52OsuSSsroNX0I5aWFFb1VrRm8/edit?usp=sharing
That example web app, contains a single page that shows the AppDomain and GetHashCode of an object that is supposed to be unique across the three frameworks, giving a result similar to:
Dependency Test
Framework IMySingletonService instance
MVC AppDomainId:2 / HashCode:5109846
WebAPI AppDomainId:2 / HashCode:5109846
SignalR AppDomainId:2 / HashCode:5109846
I hope this helps.
I am following this tutorial and I have encountered a problem with the code given for the configuration of Autofac. The code give on the tutorial is as follows:
public class AutofacConfig
{
public static void Register(HttpConfiguration config)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(WebApiApplication).Assembly);
builder.RegisterApiControllers(typeof(WebApiApplication).Assembly);
builder.RegisterType().AsImplementedInterfaces().InstancePerApiRequest().InstancePerHttpRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
When I copy this code into my MVC project I get a compile error on this line:
builder.RegisterType().AsImplementedInterfaces().InstancePerApiRequest().InstancePerHttpRequest();
The exception thrown is:
Error 1 The type arguments for method 'Autofac.RegistrationExtensions.RegisterType<TImplementer>(Autofac.ContainerBuilder)' cannot be inferred from the usage.
I have installed Autofac version 3.1.1 with NuGet. I guess something has changed in the Autofac API since the tutorial was written, but I have never worked with Autofac so have no idea how to fix this.
thanks in advance for any help. I changed to mvc4 and start using app_start/routeconfig.cs to register routes.
Probably it dont have any relation with autofac but I cannot find a solution, does anyone know if its neccesary to declare routetable.routes in any additional place - I already declared RouteConfig.RegisterRoutes(RouteTable.Routes); in global.asax - when planning to use autofac with mvc4 razor´s internet template?.
Currently no map.route definition is working in my app. I dont know if I have to declare an instance like
RegisterInstance(RouteTable.Routes);
thank you so much.
This is basically the minimum amount of code to configure Autofac for mvc. You will need to reference Autofac.Integration.Mvc, and if you're using webapi you need to reference Autofac.Integration.Webapi too.
public static class AutofacConfig
{
public static IContainer Register()
{
var assembly = typeof(MvcApplication).Assembly;
var builder = new ContainerBuilder();
builder.RegisterControllers(assembly);
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
builder.RegisterApiControllers(assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// If you don't need webapi, you can omit this, else you need Autofac.Integration.Webapi
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
return container;
}
}
In Global.Asax you can then add
AutofacConfig.Register();
in the Application_Start method as one of the first calls.