ASP.NET MVC4 Unity - Resolve dependencies on another project - asp.net-mvc

I have this configuration in my project MVC4 Unity and a generic configucion for drivers.
Bootstrapper.cs
namespace MyProyect.Web
{
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<MyProyect.Model.DataAccessContract.ICountryDao, MyProyect.DataAccess.CountryDao>();
container.RegisterType<MyProyect.Model.DataAccessContract.IContactDao, MyProyect.DataAccess.ContactDao>();
return container;
}
}
}
Global.asax:
protected void Application_Start()
{
...
Bootstrapper.Initialise();
...
}
GenericModelBinder.cs:
namespace MyProyect.Web.ModelBinder
{
public class GenericModelBinder : DefaultModelBinder//, IValueProvider
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var resolver = (Unity.Mvc4.UnityDependencyResolver)DependencyResolver.Current;
if (modelType == null)
{
return base.CreateModel(controllerContext, bindingContext, null);
}
return resolver.GetService(modelType);
}
}
}
Now that I need is to resolve a dependency in another project within the solution. My question is how I can do to that recognize the settings Unity in another project?. I currently I have this class but the current configuration does not bring in the MVC project.
namespace MyProyect.Model.ListData
{
public abstract class ListDataGenericResolver
{
protected T ResolverType<T>()
{
IUnityContainer container = new UnityContainer();
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);
//return unity.Resolve<T>();
return (T)container.Resolve(typeof(T));
}
}
}
this is a example how to use ListDataGenericResolver:
namespace MyProyect.Model.ListData.Types
{
public class CountryListData : ListDataGenericResolver, IGetListData
{
private readonly ICountryDao countryDao;
private string defaultValue;
public CountryListData(object defaultValue)
{
// Resolver
this.countryDao = this.ResolverType<ICountryDao>();
this.defaultValue = defaultValue == null ? string.Empty : defaultValue.ToString();
}
public IList<SelectData> GetData()
{
var data = this.countryDao.GetAllCountry(new Entity.Parameters.CountryGetAllParameters());
return data.Select(d => new SelectData
{
Value = d.CountryId.ToString(),
Text = d.Description,
Selected = this.defaultValue == d.CountryId.ToString()
}).ToList();
}
}
}
Thank you.

Here is how I do this.
In Application_Start, I create the unity container. I have a custom library that I use for all of my MVC projects that I import through NuGet, so I make the call to its configure method, then call the other project's Configure() methods. You could simply omit the custom library and add that code in here as well. All of that keeps my Application_Start nice and clean.
protected void Application_Start()
{
// Standard MVC setup
// <removed>
// Application configuration
var container = new UnityContainer();
new CompanyName.Mvc.UnityBootstrap().Configure(container);
new AppName.ProjectName1.UnityBootstrap().Configure(container);
new AppName.ProjectName2.UnityBootstrap().Configure(container);
// <removed>
}
This is the code for the custom MVC library's UnityBootstrap class
namespace CompanyName.Mvc
{
/// <summary>
/// Bootstraps <see cref="CompanyName.Mvc"/> into a Unity container.
/// </summary>
public class UnityBootstrap : IUnityBootstrap
{
/// <inheritdoc />
public IUnityContainer Configure(IUnityContainer container)
{
// Convenience registration for authentication
container.RegisterType<IPrincipal>(new InjectionFactory(c => HttpContext.Current.User));
// Integrate MVC with Unity
container.RegisterFilterProvider();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
}
}
Then, in the other projects, I have a UnityBootstrap there, that was called from Application_Start:
ProjectName1:
namespace AppName.ProjectName1
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
return container.RegisterType<IDocumentRoutingConfiguration, DocumentRoutingConfiguration>();
}
}
}
ProjectName2: - and you can see in here, that this one depends on some other projects in another library and it is calling their Configure() methods to get them set up too...
namespace AppName.ProjectName2
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
new CompanyName.Security.UnityBootstrap().Configure(container);
new CompanyName.Data.UnityBootstrap().Configure(container);
container.RegisterSecureServices<AuthorizationRulesEngine>(typeof(UnityBootstrap).Assembly);
return container
.RegisterType<IAuthorizationRulesEngine, AuthorizationRulesEngine>()
.RegisterType<IDateTimeFactory, DateTimeFactory>()
.RegisterType<IDirectoryInfoFactory, DirectoryInfoFactory>()
.RegisterType<IDirectoryWrapper, DirectoryWrapper>()
.RegisterType<IEmailService, EmailService>()
.RegisterType<IEntryPointService, EntryPointService>();
}
}
}
Here is the IUnityBootstrap interface that is used throughout the code above (for your reference)
/// <summary>
/// Defines a standard interface for bootstrapping an assembly into a Unity container.
/// </summary>
public interface IUnityBootstrap
{
/// <summary>
/// Registers all of the assembly's classes to their public interfaces and performs any other necessary configuration.
/// </summary>
/// <param name="container">The Unity container instance to configure.</param>
/// <returns>The same IUnityContainer object that this method was called on.</returns>
IUnityContainer Configure(IUnityContainer container);
}
I hope this helps you out.

Related

Using Unity with Web Api 2 gives error does not have a default constructor

I have ASP.NET MVC5 web application and i also have Web API in the same application. I am uisng Unity (version 4) for DI.
I am configuring the Unity container on APP start as below
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfiguration.Config();
}
}
public class UnityConfiguration()
{
public void Config()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IMyService, Myservice>();
container.RegisterType<IGenericRepository, GenericRepository>();
container.RegisterType<DbContext, MyEntities>();
}
}
public class GenericRepository:IGenericRepository
{
private DbContext _dbcontext;
public GenericRepository(DbContext dbcontext)
{
_dbcontext = dbcontext;
}
}
public class MyService:IMyService
{
private IGenericRepository _repo;
publi void MyService(IGenericRepository repository)
{
_repo = repository;
}
}
public class MyApiController:ApiController
{
provate IMyService _service;
MyApiController(IMyService myservice)
{
_service = myservice;
}
public IEnumerable<MyModel> GetData()
{
var result = _service.GetData();
return result.ConvertToMyModel();
}
}
However when i call the url like
localhost://lookup/getdata
I get error
Type 'LookupController' does not have a default constructor
How do i solve this issue? Do i need to register each controller i create with Unity or Unity automatically registers all MVC controllers?
I tend to use the Unity.Mvc-package.
You do not need to register the controllers, but you need to register Unity with WebAPI.
public class UnityConfiguration()
{
public IUnityContainer Config()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IMyService, Myservice>();
container.RegisterType<IGenericRepository, GenericRepository>();
container.RegisterType<DbContext, MyEntities>();
// return the container so it can be used for the dependencyresolver.
return container;
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Your routes...
// Register Unity with Web API.
var container = UnityConfiguration.Config();
config.DependencyResolver = new UnityResolver(container);
// Maybe some formatters?
}
}
You also need a DependencyResolver:
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();
}
}
You can also take a look at this similiar question, except for the Owin-part. Unity.WebApi | Make sure that the controller has a parameterless public constructor
I had the same error and in my case the problem was, that i forgot to register a dependency that one of the classes, I had registered for dependency injection, injects in the constructor.
In your example, could it be that you inject something into MyEntities that you forgot to Register?
Install Nuget Package Unit.WebAP instead of Unity.MVC5
Make sure the correct unity package is installed using nuget
I Installed Unity.MVC5 and was facing similar exception "parameterless constructor"
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<ICar, Tesla>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}

Asp.Net MVC and Strategy pattern

I have an MVC application that uses Entity Framework. I am using a repository, unit of work and unity as dependency injection.
The problem I have is that I have different authentication types, and each type I want a different class, so I decided to use the Strategy pattern
public interface IAuthStrategy
{
OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName);
}
public class AuthStrategy
{
readonly IAuthStrategy _authStrategy;
public AuthStrategy(IAuthStrategy authStrategy)
{
this._authStrategy = authStrategy;
}
public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
{
return _authStrategy.GetAuthenticationMechanism(userName);
}
}
public class UserNamePasswordMechanism : IAuthStrategy
{
private IInstitutionRepository _institutionRepository;
public UserNamePasswordMechanism(IInstitutionRepository institutionRepository)
{
this._institutionRepository = institutionRepository;
}
public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
{
throw new NotImplementedException();
}
}
My problem is that I am injecting IAuthStrategy into the controller, and it gives me an error, because instead of implementing IAuthStrategy, I am passing that to AuthStrategy constructor, as you can see that in my code.
How can I fix this error?
Here is my controller
public class EmployeeController : ApiController
{
private IAuthStrategy _auth;
public EmployeeController(IAuthStrategy auth)
{
this._employeeBL = employeeBL;
this._auth = auth;
}}
}
Here is unity config where i am registering my types
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
container.RegisterType<IInstitutionRepository, InstitutionRepository>();
container.RegisterType<IAuthStrategy, AuthStrategy>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Your unit registrations and classes look a little off.
From what I can gather, this is what you really want to do.
Setup a factory that will determine at runtime which IAuthStrategy should be used:
public interface IAuthStrategyFactory
{
IAuthStrategy GetAuthStrategy();
}
public class AuthStrategyFactory : IAuthStrategyFactory
{
readonly IAuthStrategy _authStrategy;
public AuthStrategy(...)
{
//determine the concrete implementation of IAuthStrategy that you need
//This might be injected as well by passing
//in an IAuthStrategy and registering the correct one via unity at startup.
_authStrategy = SomeCallToDetermineWhichOne();
}
public IAuthStrategy GetAuthStrategy()
{
return _authStrategy;
}
}
This is your existing AuthStrategy:
public interface IAuthStrategy
{
OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName);
}
public class UserNamePasswordMechanism : IAuthStrategy
{
private IInstitutionRepository _institutionRepository;
public UserNamePasswordMechanism(IInstitutionRepository institutionRepository)
{
this._institutionRepository = institutionRepository;
}
public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
{
throw new NotImplementedException();
}
}
Register the factory with unity:
container.RegisterType<IAuthStrategyFactory, AuthStrategyFactory>();
In your controller:
public class EmployeeController : ApiController
{
private IAuthStrategy _auth;
public EmployeeController(IAuthStrategyFactory authFactory)
{
this._employeeBL = employeeBL;
this._auth = authFactory.GetAuthStrategy();
}
}
Actually i missed implemented IAuthStrategyFactory on AuthStrategyFactory, once i implemented and register in unity container that worked.
Thanks

Using Unity IoC to register and resolve SignalR hubs

I think I'm missing something very simple and maybe just need a new set of eyes. I have an ASP.NET MVC application. In that app, I am using Unity for my IoC to handle dependency injection. Each of my repositories need to have a database factory injected into it and each database factory needs to have a principal injected into it. So far, I've been utilizing the PerRequestLifetimeManager to register these.
//Repositories
container.RegisterType<ChatMessageRepository>(new PerRequestLifetimeManager());
container.RegisterType<SignalRConnectionRepository>(new PerRequestLifetimeManager());
//Context
container.RegisterType<IPrincipal, Principal>(new PerRequestLifetimeManager());
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager());
container.RegisterType<UnitOfWork>(new PerRequestLifetimeManager());
Logically, I've tried to register my Hub in the same fashion.
container.RegisterType<ChatHub>(new PerRequestLifetimeManager());
However, whenever I run my app and navigate away from my chat page, I get a "Resolution of the dependency failed" exception and the InnerException tells me "Operation is not valid due to the current state of the object." I've also tried using the default (Transient), PerResolve, and ContainerControlled lifetime Unity managers when registering these guys and cannot seem to get resolve my issue.
Could someone just provide me some demo code with how you used Unity in an ASP.NET MVC application to handle dependency injection into your signalr hubs?
Here's where Unity will inject parameters into my SignalR Hub
public class ChatHub : Hub
{
private readonly ChatMessageRepository _chatMessageRepository;
private readonly SignalRConnectionRepository _signalRConnectionRepository;
private readonly UnitOfWork _unitOfWork;
public ChatHub(ChatMessageRepository chatMessageRepository,
SignalRConnectionRepository signalRConnectionRepository,
UnitOfWork unitOfWork)
{
_chatMessageRepository = chatMessageRepository;
_signalRConnectionRepository = signalRConnectionRepository;
_unitOfWork = unitOfWork;
} ... }
Thanks!
Do it in 3 steps
First. Create UnityHubActivator class
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);
}
}
Second. Create Unity container and register your dependency resolver before run Startup class
unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);
Third. Use it in your Hub
public class MyHub : Hub
{
public MyHub(Logger logger)
{
logger.Info("hub constructor");
}
}
Note. I do not change anything in my Startup class
There's a trick to do that. You will need to do something like this:
container.RegisterType< ChatHub >(new InjectionFactory(CreateChatHub));
......
and then create a private method CreateChatHub
private static object CreateChatHub(IUnityContainer container)
{
return new ChatHub();
}
1 Create "UnitySignalRDependencyResolver.cs"
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();
}
/// <summary>
/// Gets the Autofac implementation of the dependency resolver.
/// </summary>
public static UnitySignalRDependencyResolver Current
{
get { return GlobalHost.DependencyResolver as UnitySignalRDependencyResolver; }
}
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;
}
}
2.Add your resolver to Owin pipeline
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Get container
IUnityContainer container = UnityConfig.Container;
// Create resolver
var resolver = new UnitySignalRDependencyResolver(container);
// Create SignalR Configuration
var config = new HubConfiguration
{
Resolver = resolver
};
// Start SignalR
app.Map("/signalr", map =>
{
map.RunSignalR(config);
});
}
}
3.Inject your dependency in your controller's constructor
public class ValuesController : ApiController
{
private readonly IMyDependency _myDependency;
public ValuesController(IMyDependency myDependency)
{
_myDependency= myDependency;
}
}

Integrating Castle Windsor with SignalR - how should I approach this?

I am getting started with SignalR, and it works great once everything is configured. However, almost all the applications that I work on use Castle Windsor, so it would be great to be able to use them together. The reason that I want to do this is so that I can use Castle dependencies/services inside of a persistent connection.
I dug around in the source code, and it looks like I could either replace DependencyResolver with a Castle based one (i.e., Castle implementing IDependencyResolver), or I could change the usage of DependencyResolver to Castle.
Which one of these is a better idea? Is there another approach that I could use to combine Castle and SignalR?
Thanks,
Erick
August 2016 update
Following from a comment I no longer use the approach below but now use the GlobalHost.DependencyResolver
So in Global.asax.cs I initialise things
public static void Init(IWindsorContainer container)
{
var conn = configurationManager.ConnectionStrings["SRSQL"].ConnectionString;
GlobalHost.DependencyResolver.Register(typeof(IHubActivator),
() => new SignalHubActivator(container));
GlobalHost.DependencyResolver.Register(typeof(ILoggingService),
container.Resolve<ILoggingService>);
//etc or you could just pass your existing container to the resolver
GlobalHost.DependencyResolver.UseSqlServer(conn);
}
and then in the hub
private ILoggingService LoggingService{ get; set; }
public NotificationHub()
{
LoggingService = GlobalHost.DependencyResolver.Resolve<ILoggingService>();
}
and for completeness
public class SignalHubActivator: IHubActivator
{
private readonly IWindsorContainer _container;
public SignalHubActivator(IWindsorContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
var result= _container.Resolve(descriptor.HubType) as IHub;
if (result is Hub)
{
_container.Release(result);
}
return result;
}
}
OLD ANSWER from 2012
I went with the first option of setting our own DependencyResolver
AspNetHost.SetResolver(new SignalResolver(_container));
I can provide SignalResolver if desired but leaving out for readability for now.
Another important note is that the hubs must have an empty constructor so our castle container injects through properties, e.g.
public class NotificationHub : Hub, INotificationHub
{
public INotificationService NotificationService { get; set; }
and the resolver requested
public class SignalResolver : DefaultDependencyResolver
{
private readonly IWindsorContainer _container;
public SignalResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public override object GetService(Type serviceType)
{
return TryGet(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return TryGetAll(serviceType).Concat(base.GetServices(serviceType));
}
private object TryGet(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception)
{
return null;
}
}
private IEnumerable<object> TryGetAll(Type serviceType)
{
try
{
var array = _container.ResolveAll(serviceType);
return array.Cast<object>().ToList();
}
catch (Exception)
{
return null;
}
}
}
Here's what I ended up doing. First I followed along with the Windsor wiki to get my ASP.NET MVC3 setup. My Global.asax.cs:
private static IWindsorContainer _container;
protected void Application_Start()
{
BootstrapContainer();
RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
}
protected void Application_End()
{
_container.Dispose();
}
private static void BootstrapContainer()
{
_container = new WindsorContainer().Install(FromAssembly.This());
RouteTable.Routes.MapHubs(new CastleWindsorDependencyResolver(_container));
var controllerFactory = new WindsorControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
...
CastleWindsorDependencyResolver came from here
Copied:
public class CastleWindsorDependencyResolver : DefaultDependencyResolver
{
private readonly IWindsorContainer _container;
public CastleWindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
// perform the lazy registrations
foreach (var c in _lazyRegistrations)
_container.Register(c);
_lazyRegistrations.Clear();
}
public override object GetService(Type serviceType)
{
if (_container.Kernel.HasComponent(serviceType))
return _container.Resolve(serviceType);
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
IEnumerable<object> objects;
if (_container.Kernel.HasComponent(serviceType))
objects = _container.ResolveAll(serviceType).Cast<object>();
else
objects = new object[] { };
var originalContainerServices = base.GetServices(serviceType);
if (originalContainerServices != null)
return objects.Concat(originalContainerServices);
return objects;
}
public override void Register(Type serviceType, Func<object> activator)
{
if (_container != null)
// cannot unregister components in windsor, so we use a trick
_container.Register(Component.For(serviceType).UsingFactoryMethod<object>(activator, true).OverridesExistingRegistration());
else
// lazy registration for when the container is up
_lazyRegistrations.Add(Component.For(serviceType).UsingFactoryMethod<object>(activator));
// register the factory method in the default container too
//base.Register(serviceType, activator);
}
// a form of laxy initialization is actually needed because the DefaultDependencyResolver starts initializing itself immediately
// while we now want to store everything inside CastleWindsor, so the actual registration step have to be postponed until the
// container is available
private List<ComponentRegistration<object>> _lazyRegistrations = new List<ComponentRegistration<object>>();
}
public static class WindsorTrickyExtensions
{
/// <summary>
/// Overrideses the existing registration:
/// to overide an existiong component registration you need to do two things:
/// 1- give it a name.
/// 2- set it as default.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="componentRegistration">The component registration.</param>
/// <returns></returns>
public static ComponentRegistration<T> OverridesExistingRegistration<T>(this ComponentRegistration<T> componentRegistration) where T : class
{
return componentRegistration
.Named(Guid.NewGuid().ToString())
.IsDefault();
}
}
I wasn't sure WTF the HubsInstaller was trying to do from that same project but I made my own which seems to work fine (I am of course open to any suggestions why this could suck):
public class HubsInstallers : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<IHub>()
.LifestyleTransient());
}
}
Also this is for the newer SignalR versions 0.5+
dove answer is fine but it is a bit confusing, adding another more specific answer.
My main goal is this to work:
[HubName("MyHub")]
public class MyHub : Hub
{
public IJobRepository JobRepository { get; }
public MyHub(IJobRepository jobRepository)
{
JobRepository = jobRepository ?? throw new ArgumentNullException(nameof(jobRepository));
}
...
}
Of course what you want is your Hubs to be created for you, they are usually created by SignalR but now that they have some dependencies SignalR cannot create them.
SignalR itself has a Dependency Resolver (in SignalR namespace) which uses to get its own dependencies, you can add stuff to it, but we want Windsor remember?
So we are going to change just how the IHubActivator creates hubs, we are not going to use SignalR's but this one:
public class SignalRHubActivator : IHubActivator
{
private readonly IWindsorContainer _container;
public SignalRHubActivator(IWindsorContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
var result = _container.Resolve(descriptor.HubType) as IHub;
if (result is Hub)
{
_container.Release(result);
}
return result;
}
}
To replace this in SignalR container you have to do something like:
// Get an instance of the hub creator (see note below)
var _hubActivator = new SignalRHubActivator(container);
// Get the SignalR's Default Dependency Resolver
var signalRResolver = new Microsoft.AspNet.SignalR.DefaultDependencyResolver();
// Override the IHubActivator service
signalRResolver.Register(typeof(IHubActivator), () => _hubActivator);
// now map SignalR with this configuration
appBuilder.MapSignalR(new HubConfiguration { Resolver = signalRResolver });
And that's it, you should also register all your Hubs with Windsor
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(Microsoft.AspNet.SignalR.Hub)));
...
container.Register(Component.For<IJobRepository>()).ImplementedBy<JobRepository>());
Note: I registered the SignalRHubActivator as a component too, this is because the Startup class I use receives the activator as a dependency:
container.Register(Component.For<SignalRHubActivator>().
DependsOn(Dependency.OnValue("container", container)));

asp.net mvc autofac registery and resolver

I am working on ASP.NET MVC 3 application. I am using Autofac as my dependency resolver.
I have two projects one core and other UI. In the core project I have an interface which holds
information about the logged in user if any. This is inherited in my UI project.
public interface IWebContext
{
User User {get;set}
bool IsLoggedIn {get;}
}
In ui project this is implemented as
public class WebContext : IWebContext
{
//codes here to get user and islogged in proerty.
}
In the core project I am creating link based on some logic.
public static class ButtonExtension
{
public static MvcHtmlString EditButton(this HtmlHelper helper, string controller, string action, object id, string text)
{
var webContext= how to get IWebContext here.
if (!webContext.IsLoggedIn)
{
return MvcHtmlString.Empty;
}
return MvcHtmlString.Create(string.Format("{3}", controller, action, id, text));
}
}
In my global.asax I am registering all my services using IOC static class
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
IOC.Build();
}
here is my IOC class.
public static class IOC
{
private static IContainer _container;
public static void Build()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new WebContext()).As<IWebContext>().SingleInstance();
builder.Register(c => new ImageServiceLocal()).As<IImageService>().InstancePerHttpRequest();
builder.RegisterFilterProvider();
_container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
}
public static T Resolve<T>()
{
if (_container == null)
Build();
return _container.Resolve<T>();
}
}
var webContext = DependencyResolver.Current.GetRequestLifetimeScope()
.Resolve<IWebContext>();

Resources