I'm trying to use Autofac with WebApi controllers. I have :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
AutofacConfig.Register();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Here is my AutofacConfig:
public class AutofacConfig
{
public static IContainer Container { get; private set; }
public static void Register()
{
var builder = new ContainerBuilder();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
//Register repositories and services.
Container = builder.Build();
}
}
Then I'm trying to set DependencyResolver:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Filters.Add(new ExceptionHandlingAttribute());
var container = AutofacConfig.Container;//I have registered controllers here!!!
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
}
But during the request I'm receiving : "Make sure that the controller has a parameterless public constructor".
Also I've tried to set the DependencyResolver in the AutofacConfig class, just like in the tutorial
What's wrong with that?
The error message means that your controller has some dependencies that Autofac doesn't know how to inject them for you. In other words, your controller's constructor has some dependencies (parameters) that needs to be injected but those dependencies (services) themselves haven't been registered in Autofac.
If you share your controller's constructor code we would be able to identify those unregistered dependencies for you.
Related
I set DI in my Controller as shown below and tied to register IHubContext as it seen on
Controller:
public class DemoController : Controller
{
private IHubContext<DemoHub> context;
public DemoController(IHubContext<DemoHub> context)
{
this.context = context;
}
}
Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IHubContext, IHubContext>(Lifestyle.Scoped);
// or
container.Register<IHubContext>(Lifestyle.Scoped);
// code omitted
}
But when I debug my app, encounter "System.ArgumentException: 'The given type IHubContext is not a concrete type. Please use one of the other overloads to register this type. Parameter name: TImplementation'" error. So, how can I register IHubContext properly?
Since ASP.NET MVC doesn't have built in dependency injection for SignalR hub context you have to obtain a context instance using GlobalHost.ConnectionManager. With this you can register a dependency with your container that creates IHubContext instance. Considering you have typed hub
public class DemoHub : Hub<ITypedClient>
{
}
and interface
public interface ITypedClient
{
void Test();
}
register dependency as the following
container.Register<IHubContext<ITypedClient>>(() =>
{
return GlobalHost.ConnectionManager.GetHubContext<DemoHub, ITypedClient>();
}, Lifestyle.Scoped);
And the controller should look like
public class DemoController : Controller
{
private IHubContext<ITypedClient> context;
public DemoController(IHubContext<ITypedClient> context)
{
this.context = context;
}
}
I'm trying to inject my controller with Autofac. Unfortunately I am unable to configure Autofac in away so that the 'DefaultControllerActivator` wont construct my controllers?
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule<ServiceModule>();
containerBuilder.Populate(services);
containerBuilder.RegisterType<LoginController>().PropertiesAutowired();
ApplicationContainer = containerBuilder.Build();
return new AutofacServiceProvider(this.ApplicationContainer);
}
public class ServiceModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterModule(new DataProviderModule());
builder.RegisterType(typeof(LoginService)).As(typeof(ILoginService)).InstancePerRequest();
}
}
[Route("api/[controller]")]
public class LoginController : Controller
{
private readonly ILoginService _loginService;
public LoginController(ILoginService loginService)
{
_loginService = loginService;
}
}
I followed the documentation of Autofac as shown above. Unfortunately the LoginController will not be constructed because it requires an injection.
edit: If there is a way of using "Modules" without Autofac, I'd be very interesting for any suggestions :)
Thanks you in advance!
By default, ASP.NET Core will resolve the controller parameters from the container but doesn’t actually resolve the controller from the container. This usually isn’t an issue but it does mean:
The lifecycle of the controller is handled by the framework, not the request lifetime.
The lifecycle of controller constructor parameters is handled by the request lifetime.
Special wiring that you may have done during registration of the controller (like setting up property injection) won’t work.
You can change this by specifying AddControllersAsServices() when you register MVC with the service collection. Doing that will automatically register controller types into the IServiceCollection when you call builder.Populate(services).
public class Startup
{
public IContainer ApplicationContainer {get; private set;}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add controllers as services so they'll be resolved.
services.AddMvc().AddControllersAsServices();
var builder = new ContainerBuilder();
// When you do service population, it will include your controller
// types automatically.
builder.Populate(services);
// If you want to set up a controller for, say, property injection
// you can override the controller registration after populating services.
builder.RegisterType<MyController>().PropertiesAutowired();
this.ApplicationContainer = builder.Build();
return new AutofacServiceProvider(this.ApplicationContainer);
}
}
Use InstancePerLifetimeScope in ASP.NET Core. The differences between ASP.NET and ASP.NET Core like this are documented.
I wish to inject a service into a custom class i have created> i have been using Dependency injection to inject the same service into my WebApi controllers but cannot seem to understand why it doesn't work in my "InputDataValidationModel" class
This is what i am trying to do:
public class InputDataValidationModel
{
private ISec300_EE_SubmissionRepository _service { get; set; }
public InputDataValidationModel(ISec300_EE_SubmissionRepository service)
{
_service = service;
}
}
In the Global.asax i registered the types as follow:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
// Register the Controllers that should be injectable
unity.RegisterType<SEC300_EE_SubmissionController>();
unity.RegisterType<InputDataValidationModel>();
unity.RegisterType<ISec300_EE_SubmissionRepository, Sec300_EE_SubmissionRepository>(new ContainerControlledLifetimeManager());
unity.RegisterType<IClientRepository, ClientRepository>(new ContainerControlledLifetimeManager());
// Finally, override the default dependency resolver with Unity
config.DependencyResolver = new IoCContainer(unity);
}
What I cant understand specifically is that this works perfectly when done in my controller below:
public class SEC300_EE_SubmissionController : ApiController
{
private ISec300_EE_SubmissionRepository _service;
public SEC300_EE_SubmissionController(ISec300_EE_SubmissionRepository service)
{
if (service == null)
{
throw new ArgumentNullException("service");
}
_service = service;
}
}
It does not work because controllers are instantiated by Web API, and when Web API creates a controller it calls BeginScope which is the entry point to call your IoC and proceeds to resolve and constructs objects for you.
In your case InputDataValidationModel is not used and may be for this reason you don't have the instance
update
Do you perhaps have any suggestions on how i would inject my service into InputDataValidationModel ?
Option 1
You can use IDependencyResolver take a look at this link Dependency Resolution with the Unity Container`'
And after this you can resolve your service like this
var instance =GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (InputDataValidationModel));
Option 2
You might use service locator even it is an anti-pattern
static void Main(string[] args)
{
UnityServiceLocator locator = new UnityServiceLocator(ConfigureUnityContainer(
ServiceLocator.SetLocatorProvider(() => locator);
var a = ServiceLocator.Current.GetInstance<IFoo>();
var b = ServiceLocator.Current.GetInstance<IFoo>();
Console.WriteLine(a.Equals(b));
}
private static IUnityContainer ConfigureUnityContainer()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
return container;
}
Hope this help
I am trying to get Unity Container Dependency Injection working on a self-hosted owin app. I have added the Unity nuget package to my project, and have set up my UnityConfig class as follows:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDBContext,UniversalCoatingsDbContext>();
container.RegisterType<IUserRepository,UserRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Then, I set up my controller like this:
public class UserController : ApiController
{
private IUserRepository userRepo;
public UserController() {
Console.WriteLine("User controller default constructor");
}
//dependency injected value
public UserController(IUserRepository repo)
{
this.userRepo = repo;
Console.WriteLine("DI enabled constructor");
}
[HttpPost]
public JsonResult<MessageResponse> Register(UnhashedUser unhashed_user)
{
MessageResponse response = new MessageResponse();
if(ModelState.IsValid)
{
response = userRepo.createUser(unhashed_user);
}
else
{
response.message = "Invalid Request sent.";
}
return Json(response);
}
}
The UnityConfig.RegisterComponents() method is called at the end of my Startup class's Configuration() method (after all the middleware is setup). When I access this controller's URL, the parameterless constructor is always called, and thus the instance of IUserRepository is never resolved.
Am I missing some sort of configuration pattern? Any info greatly appreciated.
I modified my UnityConfig class to expose the container as a static variable. And then,
I added this to my startup class:
//set up dependency injection
UnityConfig.RegisterComponents();
config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(UnityConfig.container);
app.UseWebApi(config);
I have a property in my web api self hosted app that I would like to inject to my controllers, which is loaded via reflection using my custom IoC framework, here is my startup code:
public CustomClass StuffInstance { get; set; }
// This method is required by Katana:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var webApiConfiguration = ConfigureWebApi();
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(webApiConfiguration);
}
my controllers are mostly scaffolded and some like:
// PUT: api/EventTypeDescriptions/5
[ResponseType(typeof(void))]
public IHttpActionResult PutStuff(int id, int something)
{
//do stuff
//here i would like to use StuffInstance like a singleton
return StatusCode(HttpStatusCode.NoContent);
}
how can a inject StuffInstance to my controllers? this information would be relevant to anyone making an IoC framework btw
I found the information to inject instances to my controllers in this link:
http://www.asp.net/web-api/overview/advanced/dependency-injection
basically i implemented a dependency resolver for my custom IoC Library
in case someone has the same problem, here is the code, maybe for other IoC frameworks it needs more work
public class CustomIocDependencyResolver : IDependencyResolver
{
private readonly CustomIoc container;
public ComponentLoaderWebApiDependencyResolver(CustomIoc container)
{
this.container = container;
}
IDependencyScope IDependencyResolver.BeginScope()
{
return new CustomIocDependencyResolver(container);
}
Object IDependencyScope.GetService(Type serviceType)
{
return container.GetInstance(serviceType);
}
IEnumerable<Object> IDependencyScope.GetServices(Type serviceType)
{
return container.GetAllInstances(serviceType);
}
public void Dispose()
{
}
}
now my katana Configuration looks like:
// This method is required by Katana:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = ConfigureWebApi();
config.DependencyResolver = CustomIocDependencyResolver(container);
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(config);
}
being container the instance of my custom IoC
Since you mentioned AutoFac as a potential candidate, I recommend you follow their tutorial on WebAPI integration. You'll need to define an interface on CustomClass so that you can properly inject it.
You'll need to inject your instance that you've created (since you want to treat it as a singleton) by registering it as an instance component.
public interface ICustomClass {}
public class CustomClass : ICustomClass {}
public CustomClass _stuffInstance = new CustomClass();
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var builder = new ContainerBuilder();
var config = new HttpConfiguration();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(_stuffInstance).As<ICustomClass>();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
Then, in each controller's constructor, inject your instance that's been bound to the appropriate interface.
public class CustomController : ApiController
{
private readonly ICustomClass _customClass;
public CustomController(ICustomClass customClass)
{
_customClass = customClass;
}
}
With ASP.NET Core 6 you can now register a service provider:
builder.Services.AddScoped<ICustomClass, CustomClass>(sp => new CustomClass()/* or your already existing instance */);
builder.Services.AddSingleton<ICustomClass>(sp => new CustomClass()/* or your already existing singleton instance */);
it will be injected to your controllers:
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
private readonly ICustomClass _customClass;
private readonly ILogger _logger;
public MyController(ICustomClass customClass, ILogger<MyController> logger)
{
_customClass = customClass;
_logger = logger;
}