I want to inject my DbContext into all controllers.
public abstract class MyController: Controller
{
public MyDbContext db { get; set; }
}
protected void Application_Start()
{
[..]
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
builder.RegisterType<MyDbContext>().InstancePerHttpRequest();
}
However, when I access base.db in any controller, it is null.
What am I missing here?
Related
Consider my simple controller class where I want to use a logger (ILogger is coming from Castle in this case).
[RoutePrefix("api/orders")]
public class SignalController : ApiController
{
public ILogger Logger { get; set; } = new NullLogger();
// POST api/orders/update
[HttpPost, Route("update")]
public virtual void UpdateHandler(ChangeStateDto update)
{
this.Logger.Info($"Received ChangeStateDto with status {update.Status}");
}
}
Then I've got a self-hosted webhost, that looks like this.
public class WebHost
{
private readonly string url;
private IDisposable disposable;
private readonly ILifetimeScope scope;
public WebHost(string url, ILifetimeScope scope)
{
this.url = url;
this.scope = scope;
}
public ILogger Logger { get; set; } = new NullLogger();
// ...
public void Start()
{
try
{
this.Logger.Info($"Starting web host at {url}");
this.disposable = WebApp.Start(this.url, app =>
{
var config = new HttpConfiguration
{
DependencyResolver = new AutofacWebApiDependencyResolver(scope)
};
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
});
// ...
}
catch (Exception e)
{
// ...
this.Logger.Error(e.Message, e);
}
}
}
And this is the calling type
public class SomeCallerClass
{
public SomeCallerClass()
{
var webHostLogger = new SomeILoggerImplementation(this, "WebHost");
var builder = new ContainerBuilder();
builder.RegisterApiControllers()
.WithProperty("Logger", webHostLogger);
var container = builder.Build();
this.webHost = new WebHost("http://localhost:9000", container)
{
Logger = webHostLogger
};
}
}
Now the issue I am having is that property injection is not working for my SignalController type. It always holds a reference to the NullLogger instance. I just can't figure out why.
I solved it by using .RegisterType<> instead of .RegisterApiControllers
So the following works as expected. However I still don't understand why my first approach wasn't working.
var builder = new ContainerBuilder();
builder.RegisterType<SignalController>()
.WithProperty("Logger", webHostLogger)
.InstancePerRequest();
var container = builder.Build();
It probably wasn't working because it wasn't registering any controllers.
In your code you have:
builder
.RegisterApiControllers()
.WithProperty("Logger", webHostLogger);
However, you have to tell the registration extension which assemblies your controllers are in. You can see that in the examples shown in the docs.
Try:
builder
.RegisterApiControllers(Assembly.GetExecutingAssembly())
.WithProperty("Logger", webHostLogger);
Sorry i am new to IOC concepts. I have been trying to implement Unity.WebAPI (5.3.0.) in my web api project but getting following error;
An error occurred when trying to create a controller of type 'TransactionController'. Make sure that the controller has a parameterless public constructor
UnityResolver Class
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
Web Api Config
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
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<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
config.DependencyResolver = new UnityResolver(container);
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Controller
public class TransactionController : ApiController
{
private readonly ITransactionService _transactionService;
private readonly IMService _mService;
/// <summary>
/// Public constructor to initialize transaction service instance
/// </summary>
public TransactionController(ITransactionService transactiontService, IMService mService)
{
_mService = mService;
_transactionService = transactiontService;
}
[HttpGet]
public IHttpActionResult IsApiAlive()
{
return Ok();
}
TransactionService Class constructor
private readonly IMRepository _mRepository;
public TransactionService(IMRepository mRepository)
{
_mRepository = mRepository;
}
Check to make sure that all dependencies for the object graphs have been registered so that they can be resolved correctly.
You are most likely missing a dependency registration.
For TransactionService, you are passing/injecting the implementations in the constructors
public TransactionService(MRepository mRepository, FService fService) {
_mRepository = mRepository;
_fservice = fService;
}
while you only registered the interfaces.
container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
The resolver will do the actual initialization and injection of the implementations based on the known dependencies.
Change
public TransactionService(MRepository mRepository, FService fService)
To rely on the registered interfaces
private readonly IMRepository mRepository;
private readonly IFService fService;
public TransactionService(IMRepository mRepository, IFService fService) {
this.mRepository = mRepository;
this.fservice = fService;
}
every class involved in creating/resolving the controller needs to be checked to make sure that their dependencies can be resolved without error.
My class Is waiting for a Interface but I need initialize a class from a job in the Application_Start.
protected void Application_Start()
{
Bootstrapper.Run();
JobScheduler.RunJobSchedule();
}
On Bootstrap.Run() I have the container builder. like:
private static void SetAutofacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerRequest();
builder.RegisterAssemblyTypes(typeof(DashboardService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerRequest();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
And on JobScheduler.RunJobSchedule(); I will initializate my Jobs.
My Job need Instantiate the DashboardHelper class with IDashboardService
public class DashboardHelper
{
public IDashboardService dashboardService { get; }
public DashboardHelper(IDashboardService dashboardService)
{
this.dashboardService = dashboardService;
}
}
My Job Class:
public class ReportWeeklySenderJob : IJob
{
public IDashboardService dashboardService { get; set; }
public async Task Execute(IJobExecutionContext context)
{
this.dashboardService.Mymethods();
}
}
however I can not inject this dependency because the http context has not yet been created.
It should be a stupid question, but I could not solve it.
I have an application that is written with c# on the top of the ASP.NET MVC 5 Framework. I implemented Unity.Mvc into my project. Now, I am trying to inject dependencies objects into my SignalR Hub.
I created a class called UnityHubActivator
My class looks like this
public class UnityHubActivator : IHubActivator
{
private readonly IUnityContainer _container;
public UnityHubActivator(IUnityContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.Resolve(descriptor.HubType);
}
}
Then in my UnityConfig class I added the following to my RegisterTypes method
var unityHubActivator = new UnityHubActivator(container);
container.RegisterInstance<IHubActivator>(unityHubActivator);
My hub looks like this
[Authorize]
public class ChatHub : Hub
{
protected IUnitOfWork UnitOfWork { get; set; }
public ChatHub(IUnitOfWork unitOfWork)
: base()
{
UnitOfWork = unitOfWork;
}
}
But when I run the hub, the constructor never get called and the connection never takes place.
How can I correctly use Unity framework to inject dependencies into my hub?
UPDATED
I tried to created a custom container like so
public class UnitySignalRDependencyResolver: DefaultDependencyResolver
{
protected IUnityContainer Container;
private bool IsDisposed = false;
public UnitySignalRDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container.CreateChildContainer();
}
public override object GetService(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.Resolve(serviceType);
}
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.ResolveAll(serviceType);
}
return base.GetServices(serviceType);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if(IsDisposed)
{
return;
}
if(disposing)
{
Container.Dispose();
}
IsDisposed = true;
}
}
Then here is how I configured the hub in the Startup class
public class Startup
{
public IUnityContainer Container { get; set; }
public Startup(IUnityContainer container)
{
Container = container;
}
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
var resolver = new UnitySignalRDependencyResolver(Container);
var hubConfiguration = new HubConfiguration
{
Resolver = resolver
};
map.RunSignalR(hubConfiguration);
});
}
}
But still now working... the hub constructor never get called.
Here is how I am calling my hub from the client
<script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var app = $.connection.chatHub;
console.log('Getting things ready....');
app.client.outOfTasks = function () {
console.log('Nothing to do here')
};
app.client.logError = function (message) {
console.log(message)
};
app.client.logNote = function (message) {
console.log(message)
};
app.client.assignTask = function (taskId) {
app.server.taskReceived();
console.log('task received!!!' + taskId);
};
// Start the connection.
$.connection.hub.start().done(function () {
console.log('Connection Started....');
});
});
</script>
The UnitySignalRDependencyResolver appears accurate for that container.
Taken from the official documentation,
Dependency Injection in SignalR
try the following example for configuring Startup
public class Startup{
public void Configuration(IAppBuilder app) {
IUnityContainer container = GetContainer();
var resolver = new UnitySignalRDependencyResolver(container);
var config = new HubConfiguration {
Resolver = resolver
};
app.MapSignalR("/signalr", config);
}
IUnityContainer GetContainer() {
//...call the unity config related code.
var container = UnityConfig.Container;
//...any other code to populate container.
return container;
}
}
Make sure to register the necessary objects, including the hub (ChatHub) with the container as the container needs to know the object graph in order to resolve the necessary dependencies.
At first I started the project with asp.net mvc and unity.mvc for DI, then wanted to add web api to the same project and installed unity.webapi but with that now unity dependency injection is unable to inject service instances to the ApiControllers however the controller class are working.
UnityConfig.cs
public static class UnityConfig
{
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}
}
ApiController.cs
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService _employeeService;
public EmployeeApiController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public EmployeeApiController(){}
// GET: api/EmployeeApi
public IEnumerable<Employee> Get()
{
var a = _employeeService.GetAll();
return a;
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
On the get action of apicontroller the IService throughs a null pointer exception.
Web API defines the following interfaces for resolving dependencies:
public interface IDependencyResolver : IDependencyScope, IDisposable
{
IDependencyScope BeginScope();
}
public interface IDependencyScope : IDisposable
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
As you pointed out in your comment, the Unity.WebApi nuget package provides this implementation which you can just register in the application startup.
For full reference:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents();
}
}
Found the solution:
added the following line on the UnityConfig.cs:
public static void RegisterTypes(IUnityContainer container)
{
//Add this line
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}