I'm trying to set the container on a new app using the Dependency.SetResolver method and using autofac with autofac mvc 5 integration.
The problem is that setting the resolver doesn't appear to do anything. The default resolver will always be used and will always expect a default constructor.
Any ideas?
Edit - The global.asax.cs, I've simplified it down to:
var b = new ContainerBuilder();
b.RegisterType<UserInfo>().As<IUserSession>().InstancePerHttpRequest();
var container = b.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
And HomeController takes an IUserSession in its constructor. The exception thrown is "No parameterless constructor defined for this object." Thrown from "System.Web.Mvc.DefaultControllerActivator.Create"
You forgot to register your controllers:
b.RegisterControllers(typeof(MvcApplication).Assembly);
More info on Autofac wiki page
Related
Controller Constructor:
IRestaurantData db;
public HomeController(IRestaurantData db)
{
this.db = db;
}
// Container code
public class ContainerConfig
{
internal static void RegisterContainer(HttpConfiguration httpConfiguration)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<InMemoryRestaurantData>()
.As<IRestaurantData>()
.SingleInstance();
var container = builder.Build();
// MVC CONTROLLER VERSION
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// WEBAPI CONTROLLER VERSION
httpConfiguration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
So I'm trying to wrap my head around how Inversion of Control containers work. The course I'm in is using Autofac to create these containers. From what I'm currently understanding creating this container is making it so that when I instantiate my HomeController with IRestaurantData the container is pointing the interface AT InMemoryResataurantData everytime it is used. I can understand that much. What Im also confused by is I dont understand WHERE in the program my Controllers are are actually being instantiated? Does anyone know?
That is being done by autofac. whenever you request a class from a container, it will instantiate the type for you using the default constructor. If you have a constructor with parameters, it will look in the container for other registered types and will instantiate a new object or fetch an already used object.
Your instantiated types can be transient (short lived) or not.
So in short; when the object is requested.
I know it's been asked and answered before - the reason I'm asking is because (I think) I tried all suggested solutions to this problem but still can't resolve it.
I have an ASP.NET Web API 2.0 project. I have Autofac, Autofac.Mvc5 and Autofac.WebApi2 dependencies installed. When I try to call an API controller I get the following error:
An error occurred when trying to create a controller of type 'MyController'. Make sure that the controller has a parameterless public constructor.
In my Global.asax I have a call to IocConfig.Config() which I have placed inside App_Start:
public static class IocConfig
{
public static void Config()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyLogger>().As<IMyLogger>();
builder.RegisterApiControllers(Assembly.GetCallingAssembly());
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
WebApiApplication.Container = builder.Build();
DependencyResolver.SetResolver(
new AutofacDependencyResolver(WebApiApplication.Container));
GlobalConfiguration.Configuration.DependencyResolver =
new AutofacWebApiDependencyResolver(WebApiApplication.Container);
}
}
And this is the constructor for MyController:
public MyController(IMyLogger logger)
When I try to call it I get the specified error about the constructor. What am I missing?
I encountered this error as well and the root cause was that one of the Controller's dependencies wasn't registered correctly in Autofac.
The InnerException has the detail (in my case it was an Autofac.Core.DependencyResolutionException) and the ExceptionMessage included the detail of this dependency. Along the lines of:
"An error occurred during the activation of a particular registration... Cannot resolve parameter 'XXXX'
Check this answer.
It helps me configure correct ContainerBuilder() for WebApi controllers.
If you are looking here a solution for such error you should check your DependencyResolver Configuration first.
I faced the same issue and the problem was that I was using Autofac code samples for ContainerBuilder() object for MVC controllers and not API.
My code for register both type of controllers (MVC and Api):
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly()); //Register MVC Controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); //Register WebApi Controllers
builder.RegisterType<Type>().As<IType>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //Set the MVC DependencyResolver
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver((IContainer)container); //Set the WebApi DependencyResolver
Assembly.GetCallingAssembly() will return the calling assembly, not the assembly where your types is defined.
Assembly.GetCallingAssembly Method
Returns the Assembly of the method that invoked the currently executing method.
In order to make it works, you should use typeof(IocConfig).Assembly or Assembly.GetExecutingAssembly
You might be missing calling configuration from WebApiConfig.cs file:
IocConfigurator.ConfigureDependencyInjection(config);
ConfigureDependencyInjection can be like this:
public static void ConfigureDependencyInjection(HttpConfiguration config)
{
var builder = new ContainerBuilder();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
builder.RegisterWebApiFilterProvider(config);
// OPTIONAL: Register the Autofac model binder provider.
builder.RegisterWebApiModelBinderProvider();
// Set the dependency resolver to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
I think you are missing registering autofac at app start code.
Use this:
protected void Application_Start()
{
IocConfig.Config();
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
For more details, refer this blog http://www.codeproject.com/Articles/808894/IoC-in-ASP-NET-MVC-using-Autofac
Open you ServiceModule File
Register the Interface and service name those are mentioned in controller.
Example are as below:-
builder.RegisterType().As();
One of the classes in my Umbraco project depends on IContentService. I'm trying to provide an IContentService to this class with an IOC container.
Here is how I'm registering IContentService with my IOC (Autofac)
builder.RegisterType<Umbraco.Core.Services.ContentService>().As<IContentService>();
However, Umbraco.Core.Services.ContentService requires these constructor parameters:
public ContentService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IPublishingStrategy publishingStrategy, IDataTypeService dataTypeService, IUserService userService);
Autofac gets stuck because it doesn't know about any of these types yet. Here's a stack trace:
Exception Details: Autofac.Core.DependencyResolutionException: None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Umbraco.Core.Services.ContentService' can be
invoked with the available services and parameters:Cannot resolve parameter
'Umbraco.Core.Persistence.RepositoryFactory repositoryFactory' of constructor 'Void
.ctor(Umbraco.Core.Persistence.UnitOfWork.IDatabaseUnitOfWorkProvider, Umbraco.Core.Persistence.RepositoryFactory,
Umbraco.Core.Logging.ILogger, Umbraco.Core.Events.IEventMessagesFactory, Umbraco.Core.Publishing.IPublishingStrategy,
Umbraco.Core.Services.IDataTypeService, Umbraco.Core.Services.IUserService)'.
Which types should I register with Autofac so that my ContentService can be instantiated?
Here's how I solved this particular problem. Thanks to Claus for the help.
I need to use RegisterInstance() (docs here) instead of RegisterType<T>()
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var builder = new ContainerBuilder();
// Register the components we need resolving with Autofac
builder.RegisterInstance(applicationContext.Services.MemberService).As<IMemberService>();
builder.RegisterInstance(applicationContext.Services.ContentService).As<IContentService>();
// ... Configuration for dependency resolution here ...
}
The reason for this is that Umbraco creates an instance of ContentService and configures it correctly. Autofac needs to be told to use this instance instead of trying to create it's own.
I'm writing the web api using Dependency injection, Unit of work with the help of repositories and Autofac as the container. Dependency was getting injected perfectly 24 hours ago but suddenly when i started working today i kept on receiving the error
"Message": "An error has occurred.", "ExceptionMessage": "An error
occurred when trying to create a controller of type
'SearchController'. Make sure that the controller has a parameterless
public constructor.", "ExceptionType":
"System.InvalidOperationException",
I will include my signatures and how i am registering the types and will be really glad if someone can point out what might be going wrong with my code.
On my web api controller, i have
private IUnitOfWork<Listing> _unitOfWork = null;
public SearchController(IUnitOfWork<Listing> unitOfWork)
{
_unitOfWork = unitOfWork;
}
Unit of work takes the generic type parameter to create repository.
In my WebApiConfig.cs, I'm registering the types as below
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).InstancePerDependency();
builder.RegisterType(typeof(SearchController)).UsingConstructor(typeof(IUnitOfWork<Listing>));
I'm registering the SearchController to use the constructor which takes in IUnitOfWork<>. It was all working well before i added Mocked unit tests but for some purpose i keep on getting this error now. I've also registered the DependencyResolver
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
As there are quite a few upvotes on this question without any answers yet and I don't exactly remember how I made it work but I want to share the latest technique that has been working perfectly in many projects.
1) This is how I register my generic repsoitory and unit of work
builder.RegisterType(typeof(YourContextInRepository));
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));
2) This is how I setup the dependency resolver for my WebAPI
// Set the dependency resolver for Web API.
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
3) To register it for MVC controllers,
// Set MVC DI resolver to use our Autofac container
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
This approach works on MVC as well as WebAPI controllers and I can simply do
private IUnitOfWork<Listing> _uow;
public SearchController(IUnitOfWork<Listing> uow)
{
_uow = uow;
}
Hope it helps someone in the future.
I faced with the same issue and the problem was that I were using Autofac code samples for ContainerBuilder() object for MVC controllers and not API.
Here is a good sample how to configure it with ApiController
In application_start() I have the following code.
When the Account Controller get's created I get the parameterless constructor error.
AccountController does not have a parameterless constructor. It seems that autofac is no longer configured?
Account Controller Expects the following.
public AccountController(IFlexMembershipProvider membership, IFlexOAuthProvider openAuth)
I am not sure why autofac is not injecting the dependences?
var builder = new ContainerBuilder();
builder.RegisterType<DataContext>()
.As<IRepository>()
.As<DbContext>().InstancePerLifetimeScope();
builder.RegisterType<FlexMembershipProvider>().As<IFlexMembershipProvider>();
builder.RegisterType<FlexMembershipProvider>().As<IFlexOAuthProvider>();
builder.RegisterType<FlexRoleProvider>().As<IFlexRoleProvider>();
builder.RegisterType<UserStorage>().As<IFlexUserStore>().InstancePerLifetimeScope();
builder.RegisterType<RoleStorage>().As<IFlexRoleStore>().InstancePerLifetimeScope();
builder.RegisterType<DefaultSecurityEncoder>().As<ISecurityEncoder>().SingleInstance();
builder.RegisterType<AspnetEnvironment>().As<IApplicationEnvironment>();
builder.RegisterType<InvestorService>().As<IInvestorService>();
builder.RegisterType<InvestmentService>().As<IInvestmentService>();
builder.RegisterType<BrokerService>().As<IBrokerService>().As<IListService<Broker>>();
builder.RegisterType<PortfolioManagerService>().As<IListService<PortfolioManager>>();
builder.RegisterModelBinderProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
You need to register the assembly that contains your controllers before calling the .Build method:
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
In this example I assumed that your application class is called MvcApplication and took its assembly. If your controllers are defined in a different assembly you should specify this assembly.
The documentation of AutoFac has an example that you could have gone through.
Try add this before calling builder.Build method:
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(x => !(x.IsValueType) && !(x.IsAssignableFrom(typeof(string)))));