I gets '..make sure that the controller has a parameterless public constructor autofac..'
My controller:
public class AccountController : ApiController
{
private IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
...
}
My autofac configuration:
protected void Application_Start()
{
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<AccountService>().As<IAccountService>().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
Whats wrong with my code?
Full error message:
Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProj.Api.Controllers.AccountController' can be invoked with the available services and parameters:
Cannot resolve parameter 'MyProj.Engine.Services.Interfaces.IAccountService accountService' of constructor 'Void .ctor(MyProj.Engine.Services.Interfaces.IAccountService)'.
Fixed myself. Actually the issue was that project is Azure Mobile Service.
It was my first experience with it and I have configured it as I used to do for WebApi. But as I understood after last googling this project type base on OWIN.
That's good article about: http://blogs.msdn.com/b/azuremobile/archive/2014/04/19/autofac-and-azure-mobile-services-net-backend.aspx
So it should be like this:
ConfigOptions options = new ConfigOptions();
ConfigBuilder builder = new ConfigBuilder(options, (httpConfig, autofac) =>
{
autofac.RegisterInstance(new MyService()).As<IMyService>();
});
HttpConfiguration config = ServiceConfig.Initialize(builder);
Related
Edit #1 - Added a Unity Container to inject the mapper in the controller but facing the following error.
I have created AutoMapperConfig.cs file with the following code:
public static MapperConfiguration Configure()
{
MapperConfiguration mapperConfiguration = new MapperConfiguration(cfg => {
cfg.CreateMap<OrderDTO, Order>()
});
return mapperConfiguration;
}
Then in my global.asax.cs file under the Application_start method I added:
MapperConfiguration config = AutoMapperConfig.Configure();
IMapper mapper = config.CreateMapper();
var container = new UnityContainer();
container.RegisterInstance(mapper);
//or
//container.RegisterType<IMapper, Mapper>();
As per the documents I would do the following to use AutoMapper:
Order mapped_order = mapper.Map<Order>(orderdto);
Controller -
public class OrderController : Controller, IPersonalizable
{
private readonly IMapper _mapper;
public OrderController(IMapper mapper)
{
_mapper = mapper;
}
// GET:
public ActionResult Index()
{
Order mapped_order = _mapper.Map<Order>(order);
}
}
However, I am having trouble referencing "mapper" in my controller. I am missing some way to inject or reference it and I am struggling to understand how to do that.
Error -
IMapper No matching bindings are available, and the type is not self-bindable.Activation path: 2) Injection of dependency IMapper into parameter mapper of constructor of type OrderController<br> 1) Request for OrderController
Suggestions: 1) Ensure that you have defined a binding for IMapper.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.```
AspNet core app
1) Autofac module like that
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
//Register my components. Need to access to appsettings.json values from here
}
}
2) Module from step№1 registered into Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModule());
}
How to access to appsettings.json values from AutofacModule? I need that for create my objects inside AutofacModule and using it for DI.
Need to change step №2
public void ConfigureContainer(ContainerBuilder builder)
{
//get settigns as object from config
var someSettings= Configuration.GetSection(typeof(SomeSettings).Name).Get<SomeSettings>();
//put settings into module constructor
builder.RegisterModule(new AutofacModule(someSettings));
}
I don't know is "best practise" way or not, but it works.
So currently trying this as well.
First thing is to get the necessary nuget packages, and add them as using statements at the top of your class.
using Microsoft.Extensions.Configuration.Json;
using Autofac;
using Autofac.Configuration;
using Autofac.Extensions.DependencyInjection;
In your Program.cs Main or Startup.cs...
public static IContainer Container { get; set; }
Main() or Startup()
{
// Add the configuration to the ConfigurationBuilder.
var config = new ConfigurationBuilder();
config.AddJsonFile("appsettings.json");
var containerBuilder = new ContainerBuilder();
// Register the ConfigurationModule with Autofac.
var configurationModule = new ConfigurationModule(config.Build());
containerBuilder.RegisterModule(configurationModule);
//register anything else you need to...
Container = containerBuilder.Build();
}
This will register the configuration module into your autoFac container, after which you can then use constructor injection to pass this round...
public class YourController
{
private readonly IContainer _config;
public YourController(IContainer configuration)
{
// Use IContainer instance
_config = configuration;
}
Hope that helps somewhat, if you get any further a different way then please share.
I am trying to configure an MVC 5 application to use SignalR 2.2.x and inject a service into my NotificationsHub.
We are using Autofac for MVC but I am not sure on how to correctly configure this.
Autofac documentation exists for NuGet Autofac.Integration.SignalR (3.0.2) and Autofac.Integration.Mvc (3.3.4).
What I am doing so far is register the hubs via:
ContainerBuilder builder = new ContainerBuilder();
// Register MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ServiceForSignalRHub>().AsImplementedInterfaces();
builder.RegisterType<...>().AsImplementedInterfaces();
builder.RegisterHubs(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
However the call to .SetResolver(...) is ambigious as it exists in both MVC and SignalR integration packages. Now what? I am unable to confirm if the contructor injection of my service works for the Hub I am using.
EDIT
I can configure MVC5 with Autofac just fine. Where I get lost is how to do the same with SignalR, using the Autofac Signal integration NuGet.
Please see below.
This is my startup class:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var defaultFactory = LogManager.Use<DefaultFactory>();
defaultFactory.Directory("#D:\\NServiceBus\\ );
defaultFactory.Level(LogLevel.Debug);
var container = ConfigureAutofac(app);
ConfigureServiceBus(container, app);
app.UseAutofacMiddleware(container); // REGISTER WITH OWIN
app.UseAutofacMvc();
ConfigureAuth(app);
GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire");
ConfigureSignalR(app);
}
}
This is the part where I configure SignalR:
public partial class Startup
{
public void ConfigureSignalR(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().PropertiesAutowired();
var container = builder.Build();
//var container = new AutofacContainer().Container;
var resolver = new AutofacDependencyResolver(container);
// Any connection or hub wire up and configuration should go here
app.MapSignalR(new HubConfiguration
{
Resolver = resolver,
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
builder.RegisterInstance(resolver.Resolve<IConnectionManager>());
}
}
How can this be correctly done?
You should tell SignalR explicitly to use the AutofacDependencyResolver when you are mapping it.
I assume that you know that in your Startup class you have to call app.MapSignalR();
When you are mapping it, you should tell it to use the custom dependency resolver (the AutofacDependencyResolver).
Here's how I do it:
var resolver = new AutofacDependencyResolver(container);
app.MapSignalR(new HubConfiguration
{
Resolver = resolver
});
This way, you are telling SignalR directly which dependency resolver to use.
I have a GitHub repo for SignalR Dependency Injection, but it's not configured to use MVC. Still, I think it will give you a hint in how to create your configuration.
Note: If you are using the OWIN Middleware, be sure not to use the GlobalHost static property AT ALL since it will have massive inconsistencies.
A common error in OWIN integration is use of the GlobalHost. In OWIN
you create the configuration from scratch. You should not reference
GlobalHost anywhere when using the OWIN integration.
Again, check the repo I gave you to see how to do this.
Hope this helps:)
Best of luck!
I ended up with this (pay attention to comments):
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
IContainer container = AutofacConfig(app);
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacWebApi(GlobalConfiguration.Configuration);
var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration()
{
// Resolve presolver from container
Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(),
};
app.MapSignalR(hubConfiguration);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
_
private static IContainer AutofacConfig(IAppBuilder app)
{
var builder = new ContainerBuilder();
RegisterSignalR(builder);
return builder.Build();
}
_
private static void RegisterSignalR(ContainerBuilder builder)
{
// Register Autofac resolver into container to be set into HubConfiguration later
builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
.As<Microsoft.AspNet.SignalR.IDependencyResolver>()
.SingleInstance();
// Register ConnectionManager as IConnectionManager so that you can get
// hub context via IConnectionManager injected to your service
builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>()
.As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
.SingleInstance();
// Register hubs one by one
builder.RegisterType<MessageNotificationsHub>().ExternallyOwned();
builder.RegisterType<SystemNotificationsHub>().ExternallyOwned();
}
Thanks to #Nathan and his answer (originally found here) and logical thinking to figure out to register ConnectionManager as IConnectionManager
Install nuget package Autofac.SignalR, for example:
<package id="Autofac.SignalR" version="3.0.2" targetFramework="net471" />
Register your hubs
// during creation of the IContainer, register signalr hubs automatically
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterHubs(executingAssembly);
// alternatively register hubs individually
// ExternallyOwned() ensures SignalR is allowed to control disposal of the hubs rather than Autofac.
builder.RegisterType<NotificationHub>().ExternallyOwned();
Set signalr service locator
// replace the Signalr dependency resolver once your IContainer 'container' is ready
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
// or this can alternatively be set in the HubConfiguration instance when using OWIN IAppBuilder map.RunSignalR(hubConfiguration);
var hubConfiguration = new HubConfiguration
{
Resolver = new AutofacDependencyResolver(container),
//...
}
For more information:
https://autofaccn.readthedocs.io/en/latest/integration/signalr.html
https://learn.microsoft.com/en-us/aspnet/signalr/overview/advanced/dependency-injection
Here are the classes and interfaces I'm dealing with.
public interface IAccountService
{
//omitted for brevity...
}
public abstract class UserClientBase<T> : ClientBase<T> where T : class
{
protected UserClientBase(Binding binding, EndpointAddress remoteAddress, string userName, string password)
: base(binding, remoteAddress)
{
if (ClientCredentials == null) return;
ClientCredentials.UserName.UserName = userName;
ClientCredentials.UserName.Password = password;
}
}
public class AccountProxy : UserClientBase<IAccountService>, IAccountService
{
private static readonly WSHttpBinding Binding = WcfHelpers.ConfigureWsHttpBinding();
private static readonly EndpointAddress EndpointAddress =
new EndpointAddress(#"https://server.project.local/Project/Account/AccountService.svc");
public AccountProxy(string userName, string password)
: base(Binding, EndpointAddress, userName, password)
{
}
//omitted for brevity
}
public interface ISafeClient<out TService> : IDisposable where TService : class
{
//omitted for brevity...
}
public class SafeClient<TClient, TService> : ISafeClient<TService>
where TClient : UserClientBase<TService>, TService
where TService : class
{
//omitted for brevity...
}
public AccountController(ISafeClient<IAccountService> accountProxy)
{
_accountProxy = accountProxy;
}
I'm using Asp.net MVC 5 with Autofac integration, here are the registrations in my Global.asax Application_Start method.
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<AccountProxy>().As<IAccountService>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(SafeClient<,>)).As(typeof(ISafeClient<>)).InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Now when I try to browse to a page handled by the AccountController, I get the following exception in the URL.
None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'MyMvcApp.Controllers.AccountController' can be invoked with the
available services and parameters: Cannot resolve parameter
'Project.Client.Proxies.ISafeClient`1[Project.Client.Contracts.Service.IAccountService]
accountProxy' of constructor 'Void
I'm not sure what I'm missing here. When I look in the container's ComponentRegistry at runtime I see the Controllers and the AccountProxy. Thanks in advance.
Update:
I can inject an IAccountService successfully if I register it like this instead:
builder.Register(a => new AccountProxy("userName", "password")).As<IAccountService>();
However when I try to inject the ISafeClient I still get an exception. I think I have a larger problem here. Essentially, I'm trying to wrap a ClientBase to include safe disposing and retry logic. It handles communication and message exceptions, faulted channel states, etc. Every time I execute a method on my SafeClient, the ClientBase is re-instantiated, then automatically disposed of. If this is the case, should I even be injecting it? Ugghh.. I'm confused.
Update 2:
Looks like I can just register like this.
builder.RegisterType<SafeClient<AccountProxy, IAccountService>>().As<ISafeClient<IAccountService>>().InstancePerLifetimeScope();
Then my AccountController changes to this:
private readonly ISafeClient<IAccountService> _accountProxy;
public AccountController(ISafeClient<IAccountService> accountProxy)
{
_accountProxy = accountProxy;
}
Is there any downside to doing it this way, other than the obvious which is having to register teach safe client individually?
I have a WebAPI Controller which has a dependency on another class:
public class HealthCheckController : System.Web.Http.ApiController
{
private readonly IHealthCheckReport _healthCheckReport;
public HealthCheckController(IHealthCheckReport healthCheckReport)
{
this._healthCheckReport = healthCheckReport;
}
}
I'm using Autofac and inside the Register method of my WebApiConfig class, I've added:
var builder = new ContainerBuilder();
builder.RegisterType<HealthCheckReport>().As<IHealthCheckReport>();
var container = builder.Build();
// Set the dependency resolver for Web API.
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
But when I call the Index() action, it complains that my controller doesn't have a default constructor. Whereas, I expected Autofac just magically inject the type I have registered above.
How should this be configured?
You need to register the api controller too.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
Source: http://code.google.com/p/autofac/wiki/WebApiIntegration