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)))));
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();
I've installed nutget package MvcSiteMapProvider.MVC5.DI.Autofac.Modules.
I'm trying to register my DBContext as InstancePerRequest. This however fails with the error
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.
If I change my DBContext to InstancePerLifetimeScope, all is well. The error is thrown in the file
DI\Autofac\Modules\MvcSiteMapProviderModule.cs Line: 195
Actually, if I try to register any of my own types with InstancePerRequest, I get this error. I'm new to Autofac so don't really understand a lot of the code in the nuget package forMvcSiteMapProvider Autofac. While I'm learning more about Autofac, hoping someone can point in the right direction as to how to get around this issue?
EDIT:
From Autofac docs, I'm getting the error because:
Code is running during application startup (e.g., in an ASP.NET Global.asax) that uses dependency resolution when there isn’t an active request yet.
According to MvcSiteMapProvider docs, this line is required though, so can I move this somewhere else?
// Setup global sitemap loader (required)
MvcSiteMapProvider.SiteMaps.Loader = container.Resolve<ISiteMapLoader>();
EDIT 2:
protected void Application_Start()
{
// BEGIN: Autofac Config
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterSource(new ViewRegistrationSource());
// Register context and unit of work here
IoC.Dependencies.Register.RegisterTypes(builder);
builder.RegisterModule(new MvcSiteMapProviderModule());
builder.RegisterModule(new MvcModule());
var container = builder.Build();
MvcSiteMapProvider.SiteMaps.Loader = container.Resolve<ISiteMapLoader>();
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// END: Autofac Config
Helpers.Log4NetManager.InitializeLog4Net();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
}
You are registering your controllers twice with Autofac.
// This registers the all of the controllers in the application
builder.RegisterControllers(typeof(MvcApplication).Assembly);
// And so does this...
builder.RegisterModule(new MvcModule());
Contents of MvcModule:
public class MvcModule
: Module
{
protected override void Load(ContainerBuilder builder)
{
var currentAssembly = typeof(MvcModule).Assembly;
builder.RegisterAssemblyTypes(currentAssembly)
.Where(t => typeof(IController).IsAssignableFrom(t))
.AsImplementedInterfaces()
.AsSelf()
.InstancePerDependency();
}
}
UPDATE
From here:
The error pretty much says it all - something in your registrations has a dependency that is registered as InstancePerRequest and it's being resolved outside of a web request.
I am not sure that registering DBContext as InstancePerRequest is such a good idea. MvcSiteMapProvider loads before any request context is created, so if you are using dynamic node providers or custom ISiteMapNodeProvider implementations that access the database, it isn't going to work. A better choice would be to use InstancePerDependency which is not dependent upon HttpContext.
Instance Per Dependency
Also called ‘transient’ or ‘factory’ in other containers. Using per-dependency scope, a unique instance will be returned from each request for a service.
I am using this package to integrate Autofac with my WebApi Owin application:
https://www.nuget.org/packages/Autofac.WebApi2.Owin
And following this post:
http://alexmg.com/owin-support-for-the-web-api-2-and-mvc-5-integrations-in-autofac/
My code in Startup.cs looks like this:
var config = new HttpConfiguration();
IContainer container = EngineContext.InitializeEngine();
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = dependencyResolver;
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
WebApiConfig.Register(config);
app.UseWebApi(config);
However whichever way I spin it, rearrange the code or whatever, Autofac is just not able to resolve anything. Before Owin I had my Global.asax method working just fine:
protected void Application_Start()
{
IContainer container = EngineContext.InitializeEngine();
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
GlobalConfiguration.Configure(WebApiConfig.Register);
}
What am I missing?
Thanks
Ok,
I figured it out.
The Autofac Owin integration actually creates an Owin liftimescope, which is available through the whole Owin pipeline, thus available to middleware and extends this lifetimescope to the HttpRequestMessage. This is the lifetimescope marked with the AutofacWebRequest tag.
So all the previous WebApi integration code still needs to be performed on application startup. I have included:
var dependencyResolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = dependencyResolver;
but missed:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
in the EngineContext.Initialize method, which does all the registrations via the builder.
Here you can find more information on how to integrate Autofac with the WebApi, which obviously needs to be done also in the case of Owin:
https://code.google.com/p/autofac/wiki/WebApiIntegration
I hope this is useful!
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