I must integrate Oauth with Autofac. But something goes wrong. I think I understand why, but I don't know how to solve it. I let you see my code.
My Autofac Config
{
builder.RegisterType<CustomAuthorizationServerProvider>()
.PropertiesAutowired()
.SingleInstance();
builder.RegisterType<MyBusinessObj>()
.As<IMyBusinessObj>()
.InstancePerRequest()
.PropertiesAutowired();
//IMySessionObj is a prop inside MyBusinessObj
builder.RegisterType<MySessionObj>()
.As<IMySessionObj>()
.InstancePerRequest()
.PropertiesAutowired();
//IMyUnitOfWorkObjis a prop inside MyBusinessObj
builder.RegisterType<MyUnitOfWorkObj>()
.As<IMyUnitOfWorkObj>()
.InstancePerRequest();
...
}
Startup.cs
I have the classic configuration plus the resolution of my authorizationServerProvider.. As you can see, I resolve it in the container... because it is a singleton.
app.UseAutofacMiddleware(_container);
app.UseAutofacWebApi(config);
var oauthServerOptions = new OAuthAuthorizationServerOptions
{
...,
Provider = _container.Resolve<CustomAuthorizationServerProvider>()
};
app.UseOAuthAuthorizationServer(oauthServerOptions);
app.UseWebApi(config);
CustomAuthorizationServerProvider.cs
This is how I have implemented my CustomAuthorizationServerProvider.
public class CustomAuthorizationServerProvider: OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
var autofacLifetimeScope = OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>();
var xxx = myBusinessObj.DoWork();
...
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var myBusinessObj = autofacLifetimeScope.Resolve<IMyBusinessObj>();
var xxx = myBusinessObj.DoWork();
...
context.Validated(ticket);
}
}
Here I solve my IMyBusinessObj in a lifetimescope, not in the container. This object is responsible (indirectly) to connect to db, access the session, access the cache and so on... so it cannot be a singleton.
I need it would have a lifetime per request.
So here the problems.. Two problems there are in my configuration.
I have a InstancePerRequest object inside a SingleInstance object. I cannot do that. Troubleshooting Per-Request Dependencies
I effectively cannot have a InstancePerRequest object when I configure oauth in the startup... because in that context does not exist a request yet.
So.. I have understood which are my problems.
Any idea or tips?
Thank you
I was having a very similar issue if not the same. I was able to resolve it by doing the following:
1. Do not resolve IOAuthAuthorizationServerProvider directly from the container. Instead, use IDependencyResolver. In your example:
var oauthServerOptions = new OAuthAuthorizationServerOptions
{
...,
Provider = (IOAuthAuthorizationServerProvider)resolver.GetService(typeof(IOAuthAuthorizationServerProvider)),
};
This requires that you have correctly configured HttpConfiguration.DependencyResolver:
HttpConfiguration config = new HttpConfiguration();
... // Configure unrelated
var builder = new ContainerBuilder();
... // set Autofac registrations
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// THIS is where you configure OAuthAuthorizationServerOptions, using IDependencyResolver to resolve IOAuthorizationServerProvider instead of IContainer
ConfigureAuth(app, config.DependencyResolver);
2. I was using dynamic assembly scanning to configure certain Autofac module registrations. I inadvertently was scanning for classes ending with "Provider" and registering them as RequestPerInstance(). This was a problem for me, as it was re-registering my IOAuthAuthorizationServerProvider as a per-request instance, which is unable to be resolved during Startup() code.
Problem code which I replaced with individual registrations:
builder.RegisterAssemblyTypes(executingAssembly)
.Where(t => t.Name.EndsWith("Provider"))
.AsImplementedInterfaces()
.InstancePerRequest();
3. Check properties of MySessionObj, and see what dependencies Autofac is resolving (if any). Make sure that you are explicitly registering dependencies as InstancePerRequest().
By using OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);, you are resolving dependencies to the "AutoFacWebRequest" lifetime scope, and not the root scope. As a result, my understanding is dependencies resolved to this lifetime scope should be disposed after the request has finished and shouldn't cause future problems with your application.
4. I am not sure what properties are being autowired for your CustomAuthorizationServerProvider object, but assuming you did not post a complete code sample for this class, I would try removing PropertiesAutowired() from it's Autofac registration and inside the object continue to use OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext); to resolve these other properties if possible.
Could you provide specific detail about what the error or error message you are observing is?
Related
I use Unity in an MVC5 project (.net461) for DI and I want to register a service with multiple lifetimes.
With the classic core DI I would use RegisterScoped and that's it. Whenever the service is resolved within an Http Request I would reuse the same instance for the duration of the request. If I want to fire a background task, that background task should open a service scope, and I would resolve a new instance for the service for the duration of that scope. No need to have different registrations for the service. In the first case, the scope is created by the runtime, and in the second it is manually created by the developer. In both cases, the service provider only knows that the service is scoped, it doesn't care about where and how the scope has opened.
With Unity the first case is solved with PerRequestLifetimeManager. The second case is solved with a HierarchicalLifetimeManager.
But how should I have a combination of the two?
Whenever a service is resolved within an HttpRequest (in a controller constructor for instace) it should use the PerRequestLifetimeManager and wherever it is resolved in a child container (within the constructor of another service that is instantiated in the child container) it should use HierarchicalLifetimeManager.
How can I register the service with both managers?
At the end of the day, I had to implement my own solution which is based on (but not using) Unity.Mvc, Unity.WebApi packages, and the HierarchicalLifetimeManager.
None of the solutions I found online worked for my case. Most of them covered only the per request part, but not the per custom user scope part.
The key of the solution is not the lifetime manager but the dependency resolver. The lifetime manager for my requirements should always be HierarchicalLifetimeManager because that is what I truly need. A new container for each scope, which is covered by child containers and HierarchicalLifetimeManager.
Using Integrating ASP.NET Core Dependency Injection in MVC 4 as an example on how to implement your own dependency resolver, I came up with the solution below.
What I had to do, is to make sure a new scope is created on the beginning of the Http Request, and Disposed at the end of the Http Request. This part is covered by implementing a simple HttpModule. This part is similar to the HttpModule used by the official Unity Per Request Lifetime implementation.
Per Http Request Module
This is the module implementation
internal class UnityPerHttpRequestModule : IHttpModule
{
private static IUnityContainer _rootContainer;
public void Init(HttpApplication context)
{
context.BeginRequest += (s, e) =>
((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
= _rootContainer.CreateChildContainer();
context.EndRequest += (s, e) =>
(((HttpApplication)s).Context.Items[typeof(UnityPerHttpRequestModule)]
as IUnityContainer)?.Dispose();
}
public static void SetRootContainer(IUnityContainer rootContainer)
{
_rootContainer = rootContainer ?? throw new ArgumentNullException(nameof(rootContainer));
}
public void Dispose() { }
}
On Beginning the request we create a new child container and place it in the HttpRequest Items dictionary.
On Ending the request we retrieve the child container from the Items dictionary and dispose it.
The static method SetRootContainer should be called once at the startup of the application to pass in the initial root Unity container, the one that services are registered on.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
UnityPerHttpRequestModule.SetRootContainer(UnityConfig.Container); // pass here the root container instance
...
}
}
We also need to register the module with owin.
using Microsoft.Owin;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Owin;
[assembly: OwinStartup(typeof(MyApp.Startup))]
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.Startup), nameof(MyApp.Startup.InitScopedServicesModule))]
namespace MyApp
{
public partial class Startup
{
public static void InitScopedServicesModule()
{
DynamicModuleUtility.RegisterModule(typeof(UnityPerHttpRequestModule));
}
public void Configuration(IAppBuilder app)
{
}
}
}
MVC Dependency Resolver
Now the http module is registered and we have a new scope created on each request. Now we need to instruct MVC and WebApi to use that scope. For this, we need to create the appropriate dependency resolvers. I created one dependency resolver for MVC and one for WebApi since they need to implement different interfaces (I could have implemented both in the same class though).
The dependency resolver for MVC is this:
internal class UnityMvcPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityMvcPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public void Dispose() { }
public object GetService(Type serviceType)
{
try
{
return Current.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return Current.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
}
What the resolver does is that it checks for an HTTP Context and gets the unity container in the Context's item dictionary and uses this container to resolve the services. So effectively, if the service requested is registered with a Hierarchical Lifetime, a new instance of that service will be created within the child container (aka within the context of the request). Since the child container is disposed at the end of the request by the http module, any services instantiated in the child container are also disposed.
Things to notice here:
The IDependencyResolver interface here is the System.Web.Mvc.IDependencyResolver. This is the interface expected by the MVC. The WebApi expects a difference IDependencyResolver (same name, different namespaces)
Catching ResolutionFailedException. If you don't catch those exceptions, the application will crash.
Now that we have the MVC dependecy resolver, we need to instruct MVC to use this resolver.
public static class UnityMvcActivator
{
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
//DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityMvcPerHttpRequestDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
//Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
}
Things to notice here:
Do not register the official UnityPerRequestHttpModule since we implement our own. ( I could probably use that module but my implementation would depend on the inner implementation of the official module and I don't want that, since it may change later)
Web Api Dependency Resolver
Simlilar to MVC dependency resolver, we need to implement one for the Web Api
internal class UnityWebApiPerHttpRequestDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer rootContainer;
internal UnityWebApiPerHttpRequestDependencyResolver(IUnityContainer rootContainer)
{
this.rootContainer = rootContainer;
}
internal IUnityContainer Current => (HttpContext.Current?.Items[typeof(UnityPerHttpRequestModule)] as IUnityContainer) ?? this.rootContainer;
public IDependencyScope BeginScope() => this;
// Dispose, GetService and GetServices are the same as MVC dependency resolver
}
Things to notice here:
IDependencyResolver here is of type System.Web.Http.Dependencies.IDependencyResolver. It is not the same as MVC's IDependencyResolver.
This Dependency resolver interface implements one more method: BeginScope. This is important here. WebApi pipeline is different that MVC pipeline. WebApi engine, by default, calls BeginScope to open a new scope for each web api request, and uses that scope to resolve controllers and services. So, Web api has already a scoped mechanism. BUT we have already created a scope ourselves with our per request module and we want to use that scope. So what we have to do here is to not create a new scope again. It already exists. So calling BeginScope on our resolver should return the same resolver scope, thus we return this.
Now that we have created the WebApi resolver, we have to also register it to web api.
using System.Web.Http;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.UnityWebApiActivator), nameof(MyApp.UnityWebApiActivator.Start))]
namespace MyApp
{
/// <summary>
/// Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET.
/// </summary>
public static class UnityWebApiActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use
// a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);
var resolver = new UnityWebApiPerHttpRequestDependencyResolver(UnityConfig.Container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
}
}
Registering services
Now that we have set up and registered all our Resolvers and modules, the last thing to do is to remember to register each scoped service with HierarchicalLifetimeManager. Since our scoped solution depends on child containers, registering our scoped services that way will suffice.
Conclusion
And with that, I managed to implement a working scoped DI solution with Unity. The example below did not work with the official Per Request Lifetime solution, but worked with my custom implementation.
class TestController{
private readonly IMyScopedService service;
private readonly IUnityContainer container;
public TestController(IUnityContainer container, IMyScopedService service){
this.service = service;
this.container = container;
}
public ActionResult Post( ... ){
var childContainer = this.container.CreateChildContainer();
var scopedService = childContainer.GetService<IMyScopedService>()
HostingEnviroment.QueueBackgroundWorkItem(() => {
using(childContainer){
scopedService.DoWork();
}
});
}
}
With the official PerRequestLifetimeManager solution, this.service and scopedService were the same instance. The scoped service was instantiated in the http context, then the same instance was fetched again from the child container (since it was registerd with PerRequestLifetimeManager and not HierarchicalLifetimeManager) and passed to the background Job. The background job outlives the http request. The instance is disposed when the Http requests ends, but it is still being used in the background job which probably runs in another thread. Concurrency issues (and more) arise. For instance you can't use the same instance of an EF DbContext in multiple threads.
With the custom implementation above, the example works. scopedService is a different instance since it is registered with a HierarchicalLifetimeManager. this.services is disposed when the http request ends but scopedService lives during the whole execution of the background Job.
What we effectively do is control the lifetime of the services by controlling the lifetime of child containers. And I have the impression that this is the solution for every scoped service scenario.
Register all scoped services with HierarchicalLifetimeManager
Control the lifetime of services by controlling the lifetime of the child containers.
I would like to use ASP.NET Core's default DI container to setup DI for my Service Fabric project.
//This is what I've got so far, and it works great
ServiceRuntime.RegisterServiceAsync(
"MyServiceType",
context => new MyService(context, new MyMonitor()
).GetAwaiter().GetResult();
//This is how I use it
public MyService(StatefulServiceContext context, IMonitor myMonitor)
: base(context)
{
this._myMonitor = myMonitor;
}
How would I set up DI, if MyMonitor class has a dependency on a ConfigProvider class, like this:
public MyMonitor(IConfigProvider configProvider)
{
this._configProvider = configProvider;
}
I think this question will give you some light: Why does ServiceRuntime.RegisterServiceAsync return before the serviceFactory func completes?
Technically, the ServiceRuntime.RegisterServiceAsync() is a dependency registration, it requires you to pass the serviceTypeName and the factory method responsible for creating the services Func<StatelessServiceContext, StatelessService> serviceFactory
The factory method receives the context and returns a service (Stateful or stateless).
For DI, you should register all dependencies in advance and call resolve services to create the constructor, something like:
var provider = new ServiceCollection()
.AddLogging()
.AddSingleton<IFooService, FooService>()
.AddSingleton<IMonitor, MyMonitor>()
.BuildServiceProvider();
ServiceRuntime.RegisterServiceAsync("MyServiceType",
context => new MyService(context, provider.GetService<IMonitor>());
}).GetAwaiter().GetResult();
PS:
Never Register the context (StatelessServiceContext\StatefulServiceContext) in the DI, in a shared process approach, multiple partitions might be hosted on same process and will have multiple contexts.
This code snippet is not tested, I've used in the past, don't have access to validate if matches the same code, but is very close to the approach used, might need some tweaks.
Hi #OscarCabreraRodrĂguez
I am working on the project that simplifies development of Service Fabric Reliable Services and it has great built-in support for dependency injection scenarios.
You can find general information project page, wiki and specific information about dependency injection here.
The idea is that project abstracts you from working with Service instance directly instead providing you with a set of more concrete objects.
Here is a simple example for ASP.NET Core application:
public static void Main(string[] args)
{
new HostBuilder()
.DefineStatefulService(
serviceBuilder =>
{
serviceBuilder
.UseServiceType("ServiceType")
.DefineAspNetCoreListener(
listenerBuilder =>
{
listenerBuilder
.UseEndpoint("ServiceEndpoint")
.UseUniqueServiceUrlIntegration()
.ConfigureWebHost(
webHostBuilder =>
{
webHostBuilder
.ConfigureServices(
services =>
{
// You can configure as usual.
services.AddTransient<IMyService, MyService>();
})
.UseStartup<Startup>();
});
});
})
.Build()
.Run();
[Route("api")]
public class ApiController : Controller
{
public ApiController(IMyService service) { }
[HttpGet]
[Route("value")]
public string GetValue()
{
return $"Value from {nameof(ApiController)}";
}
}
Hope I understand your use case correctly and this information is relevant.
In one of my web applications, I have a web service that is using Autofac, the svc file is as follows:
<%# ServiceHost Language="C#" Debug="true"
Service="MyApp.WebServices.Contracts.Interfaces.IMyWebService, MyApp.WebServices.Contracts"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf" %>
I register the dependencies for my web service application like this:
public class IocConfig
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
//web services
builder.RegisterType<MyWebService>().As<IMyWebService>().InstancePerLifetimeScope();
var container = builder.Build();
AutofacHostFactory.Container = container;
}
}
From another web application, I want to connect to those services also using Autofac, so I register the dependencies like:
public class IocConfig
{
//Ioc dependencies for frontend application
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder
.Register(c => new ChannelFactory<ISomeWebService>(
new BasicHttpBinding(),
new EndpointAddress("http://localhost/MyApp.WebServices/MyWebService.svc")))
.InstancePerLifetimeScope();
//register service proxies
builder.Register(c => c.Resolve<ChannelFactory<IMyWebService>>().CreateChannel())
.As<IMyWebService>()
.UseWcfSafeRelease();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
Inside one of the controllers, I do the following:
public SomeController(IMyWebService myServiceProxy)
{
_myServiceProxy = myServiceProxy;
var response =_myServiceProxy.CallSomeMethod(new Request()
{
EmailAddress = "test#test.com"
});
}
The myServiceProxy of type IMyWebService is being resolved, I see that it is a transparent proxy, but when I call the "CallSomeMethod" I get an error:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
What am I doing wrong here? Thanks!
Per the docs, WCF doesn't support per-request lifetime scope. If your service implementation is taking dependencies, you can't register them as per request.
There is an FAQ telling you how to troubleshoot this and alternatives you can use.
I have an existing MVC application that is using Dependency Injection with Ninject. I installed the Ninject.MVC3 nuget package and it creates a class called NinjectWebCommon in my App_Start, which completely isolates the kernel and registers all of my bindings:
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFoo>().To<Foo>();
}
We have a new requirement that we thought SignalR would be able to satisfy, so we installed SignalR 2 nuget package into the project. I created a Hub and did some searching on how to implement Dependency Injection into the project and found an article that suggests creating a SignalRDependencyResolver. http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection
The article has you creating a kernel in the Startup.cs file that is used for registering SignalR in OWIN:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var kernel = new StandardKernel();
var resolver = new NinjectSignalRDependencyResolver(kernel);
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
var config = new HubConfiguration()
{
Resolver = resolver
};
app.MapSignalR(config);
}
}
The problem is that this approach has me creating two different kernels and they seem to have their own set of dependencies that they know how to resolve. If I have a dependency defined in NinjectWebCommon, the Hub doesn't know how to resolve that dependency. Without exposing my kernel in NinjectWebCommon, what is the proper way to add DI into SignalR using the Ninject.MVC3 package?
None of the current answers directly answer your question. Also achieving the result you are after is very straightforward once you know exactly what to do. The "proper" way to do this is to set SignalR's dependency resolver in the CreateKernel method of the NinjectWebCommon class.
Assuming you have created a NinjectSignalRDependencyResolver class as you mention, no other code needs to be added anywhere except for the line highlighted in the code snippet below:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// THIS LINE DOES IT!!! Set our Ninject-based SignalRDependencyResolver as the SignalR resolver
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
Apart from the above, nothing more needs to be done except declaring your bindings in the RegisterServices method of NinjectWebCommon. In your example this would look like:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IStockTicker>()
.To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>() // Bind to StockTicker.
.InSingletonScope(); // Make it a singleton object.
kernel.Bind<IHubConnectionContext>().ToMethod(context =>
resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients
).WhenInjectedInto<IStockTicker>();
}
Except for the NinjectSignalRDependencyResolver class you created, no other code needs to be added. Importanly, the OwinStartup class remains unmodified, as follows:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
The above example achieves the following important outcomes which were what you asked in your question:
You only have a single Ninject Kernel created
The kernel and all binding configurations remain confined to NinjectWebCommon
The default SignalR resolver is your NinjectSignalRDependencyResolver
Dependency Injection into all SignalR hubs is achieved
Hopefully this helps people out.
Have you tried adding the StockTickerHub itself to your kernel?
By default, SignalR uses Activator.CreateInstance to construct Hubs without any constructor arguments. If you want to inject your own dependencies into a Hub, you can do so by registering the Hub with SignalR's dependency resolver.
https://github.com/SignalR/SignalR/blob/2.0.1/src/Microsoft.AspNet.SignalR.Core/Hubs/DefaultHubActivator.cs#L28
If you want to get really creative, you can register your own IHubActivator instead of registering all of Hubs individually.
I go into more detail in how Hubs are created by default in this answer: SignalR with IoC (Castle Windsor) - which lifetime for hubs?
There is a problem with the singleton scope. I don´t know who should get the blame here (Ninject, SignalR, MVC, etc...), but it works if you use ToConstant:
var binding = Bind<IMustBeSingleton>().ToConstant(new MustBeSingleton());
I had the same problem, and I found the solution: SignalR, WebAPI and MVC sharing the same dependency resolver kernel
I shared a complete solution with MVC, WebAPI and SignalR using the same Ninject kernel: https://drive.google.com/file/d/0B52OsuSSsroNX0I5aWFFb1VrRm8/edit?usp=sharing
That example web app, contains a single page that shows the AppDomain and GetHashCode of an object that is supposed to be unique across the three frameworks, giving a result similar to:
Dependency Test
Framework IMySingletonService instance
MVC AppDomainId:2 / HashCode:5109846
WebAPI AppDomainId:2 / HashCode:5109846
SignalR AppDomainId:2 / HashCode:5109846
I hope this helps.
I've set up a Web API project using Ninject, and I've used the fix detailed here for getting it to work with the latest version of the Web API. Everything is working fine, but I'm now trying to write some tests.
I'm using in-memory hosting to run the project for the tests, as detailed here, as I have a DelegatingHandler that performs authentication and then sets a property on the request message that is used by all the Api Controllers.
So, I've got a base class for my tests, and have a SetUp method where I set up the HttpServer and configuration, which I've pretty much taken from my working Ninject code:
[SetUp]
public void Setup()
{
bootstrapper = new Bootstrapper();
DynamicModuleUtility.RegisterModule(
typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(
typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("Login",
"api/auth/token",
new { controller = "Users", action = "Login" });
config.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always;
config.DependencyResolver =
new NinjectResolver(CreateKernel());
config.MessageHandlers.Add(
new AuthenticationHandler(CreateUserManager()));
Server = new HttpServer(config);
}
This is how I create the MoqMockingKernel:
private static IKernel CreateKernel()
{
var kernel = new MoqMockingKernel();
kernel.Bind<Func<IKernel>>()
.ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>()
.To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver =
new NinjectResolver(kernel);
return kernel;
}
And this is how I register the objects to use:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserManager>().ToMock();
kernel.Bind<UsersController>().ToSelf();
}
While I'm not testing the Controller per se, I do want a proper instance of it to be called, which is why I'm binding it ToSelf. I must admit that I am assuming that this is correct. This is an example of a test:
public void UserCannotLogin()
{
System.Net.Http.HttpClient client =
new System.Net.Http.HttpClient(Server);
string json = string.Format(
"{{ \"Username\": \"{0}\", \"Password\": \"{1}\" }}",
"wrong", "wrong");
HttpRequestMessage request =
CreateRequest(#"api/auth/token", json, HttpMethod.Get);
Action action = () => client.SendAsync(request);
using (var response = client.SendAsync(request).Result)
{
response.StatusCode.Should()
.Be(HttpStatusCode.Unauthorized);
}
}
I'm basically getting a 404 error. When I debug it, it does go to my DelegatingHandler, but it doesn't go to my controller.
I get the feeling that I'm fundamentally missing a point here, and it may not even be possible to do what I'm trying to do, but if anyone has any suggestions for either how to do this, or a different way to achieve the same thing, I'm all ears.
Update I think that it's because the default behaviour of the MockingKernel is to provide a Mock unless told otherwise, so it is returning a Mock of IHttpControllerSelector. I've set up a couple of default ones now:
kernel.Bind<IHttpControllerSelector>()
.To<DefaultHttpControllerSelector>();
kernel.Bind<IContentNegotiator>()
.To<DefaultContentNegotiator>();
It's still not working, I think because there are no formatters specified. I'll try that tomorrow and see if that gets me there.
Ok, I think that I was correct when I said that I was fundamentally missing a point here, but I'll answer this in case it helps someone else avoid the same mistake!
The Ninject MockingKernel is, I think, primarily about auto-mocking, so where you have a lot of interfaces you don't care about how they are set up in your test, you can ignore them in your tests and they will be automatically created for you.
In the case of the Web API, this is most definitely not the case, as you don't want the controller selector class to be auto mocked, otherwise you won't end up calling your controllers.
So, the solution I've come up with is to stick with using a standard Ninject Kernel, and then bind your interface to a constant Mock object:
kernel.Bind<IUserManager>().ToConstant(CreateUserManager());
private IUserManager CreateUserManager()
{
Mock<IUserManager> userManager = new Mock<IUserManager>();
// Set up the methods you want mocked
return userManager.Object;
}
Doing this, I've been able to successfully write tests that use an HttpClient to call an in-memory HttpServer that successfully call my DelegatingHandler and then end up at my controllers.