This one is driving me mad. I've read the Ninject docs, I've read the docs for the Ninject MVC extension, I've lost count of how many related SO questions I've read, and I have no idea where the problem is with my code.
I'm building a webapp in ASP.NET MVC 4, and I'm using Ninject to bind repository interfaces. The docs say that if you add Ninject using NuGet (which I did), then it wires everything up for you so you don't need to have your application inherit from NinjectHttpApplication (so I haven't) and you just need to add your bindings in NinjectWebCommon.RegisterServices(), (which I have). I have an IRepository<T>, and a Repository<T>. The user repository has a few extra methods for login and registration, so there's a separate UserRepository which implements IRepository<User>. My bindings therefore look like this:
kernel.Bind(typeof(IRepository<>)).To(typeof(BaseRepository<>)).InRequestScope();
kernel.Bind(typeof(IRepository<User>)).To(typeof(UserRepository)).InRequestScope();
The docs, and a couple of SO questions, also mention that if you added Ninject though NuGet (which I did) then it sorts out the controller factory for you and you don't need to implement your own Ninject-y controller factory (so I haven't). My controllers inherit from a BaseController, which has a constructor that accepts a set of IRepository-compatible repositories. Now, from what I've read, when I try to use a controller, Ninject should recognise the IRepositoriy parameters and provide them. It doesn't. Even if I put the [Inject] attribute on the constructor, it still gets ignored - the parameterless constructor gets called instead. If I remove the parameterless constructor, I get a compile error complaining that there isn't one.
What have I missed? How do I get Ninject to provide my repositories?
Weird, I am unable to reproduce the problem you are describing.
Steps:
Create a new ASP.NET MVC 4 application using the Internet template
Install the Ninject.MVC3 NuGet
Define some classes:
public interface IRepository<T>
{
}
public abstract class BaseRepository<T> : IRepository<T>
{
}
public class User
{
}
public class UserRepository : BaseRepository<User>
{
}
public abstract class BaseController<T>: Controller
{
protected BaseController(IRepository<T> repository)
{
this.Repository = repository;
}
protected IRepository<T> Repository { get; private set; }
}
public class HomeController : BaseController<User>
{
public HomeController(IRepository<User> repository): base(repository)
{
}
public ActionResult Index()
{
return Content(this.Repository.GetType().ToString());
}
}
And wire them up in ~/App_Start/NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel
.Bind(typeof(IRepository<User>))
.To(typeof(UserRepository))
.InRequestScope();
}
Run the application and the proper instance of the repository gets injected into HomeContorller.
Related
I am using Jersey 2.8 with Glassfish 4.0.
I have a resource locator class which looks like below
#Path("/")
#ManagedBean
public class MyServiceLocator {
#Context
ResourceContext rc;//javax.ws.rs.container.ResourceContext
#EJB
private MyEJBHome myEJB;
#Inject//javax.inject.Inject
MySubService mss;
#Path("/mysubservice")
public MySubService getMySubService() {
return rc.getResource(MySubService.class);
//also tried return rc.initResource(new MySubService());
}
}
and a sub resource class which is
#ManagedBean
public class MySubService {
#EJB
public MyEJBHome myEJB;
#Context
HttpHeaders heads;
/*#Inject
private myEJBHome myEJB2;*/
#Path("/mypath")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Object doSomething(#Context SecurityContext securityContext) {...}
}
beans.xml file is put to META-INF and WEB-INF.
In MyServiceLocator class private MyEJBHome myEJB is injected successfully. And MySubService mss object is injected successfully and with EJB injected into it.
The problem is that when MySubService is got via ResourceContext the EJB is not injected into it.
Previously i used Glassfish 3 and Jersey 1.17 with proprietary ResourceContext and absolutely the same code worked ok.
I googled a lot and read a lot of similar (but a bit different) questions and as i understood non JAX-RS stuff (EJB in my case) can't be injected when sub resource is got via ResorceContext. Is it true? If yes how can i work it around?
The one possible solution is to inject sub resource objects to the resource locator class but there are too many of them and it seems to be very ugly.
EDIT Injection with #Inject works if to create a binder, bind ejb class to ejb interface and register that binder. But i don't want to describe binding for hundreds of my ejbs. Also as i understand it is specific binding fir HK2 system and i don't want to be linked to it.
Different actions with setting #Named annotations and trying to inject via CDI didn't help. It seems that when getting sub-resource via ResourceContext Jersey uses only HK2 and that's why CDI can't do it's work. Is that correct?
The only appropriate solution i found was to create my own annotation and inject provider.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface EJBInject {
String beanName();
}
#Provider
public class EjbInjectProvider implements InjectionResolver<EJBInject> {
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
try {
String beanName = injectee.getParent().getAnnotation(EJBInject.class).beanName();
return new InitialContext().lookup("java:global/MyApp/" + beanName);
} catch (Exception e) {
return null;
}
}
#Override
public boolean isConstructorParameterIndicator() {
return false;
}
#Override
public boolean isMethodParameterIndicator() {
return false;
}
}
Then ejb can be injected using that annotation like
#EJBInject(beanName="MyBean")
MyBeanEJBHome myBean;
In such case any standard EJB injections which MyBeanEJBHome might need work correctly, too.
My current setup is using Ninject for simple IoC, everything goes fine, but I'm not able to resolve one of the classes I need inside my AuthorizeAttribute. I need to access a class that does ClaimsVerification:
Here's my code:
IoC Config:
var kernel = new StandardKernel(); // Ninject IoC
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<ISmartDocumentorUow>().To<SmartDocumentorUow>();
kernel.Bind<IClaimsVerification>().To<ClaimsVerification>();
// kernel
//kernel.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
MyAuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
IClaimsVerification clamisverify { get; set; }
public MyAuthorizeAttribute()
{
//var x = System.Web.Mvc.DependencyResolver.Current.(typeof(IClaimsVerification));
}
Yap, sorry, the problem was injecting the iClaimsverification that isn't working in web api..
I tryed with the public property and still it didn't work.
the bindfilter is commented out, because it doesn't exist in the core NInject api (dll), it does exists in the MVC dll of ninject but it works for Action filters in the web mvc, and not in the api mvc for what i can tell..
i do solved the issue like this, though i don't like a lot of this fix:
private IClaimsVerification verifier
{
get
{
return (GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IClaimsVerification)) as IClaimsVerification);
}
}
The property you have marked with Inject is private - you need to initialize Ninject with a custom configuration to opt into what would be a much less efficient process
(You didnt state the problem in your question. I see you were trying BindFilter, but it's commented out (why?) - this is the correct approach. I recommend reading the Ninject.MVC3 wiki article on BindFilter for an example)
I am currently using Ninject (2.2.1.4) and Ninject.Extensions.Wcf (2.2.0.4) with my WCF service. I would like to upgrade to Ninject (3.0.0.15) and Ninject.Extensions.Wcf (3.0.0.5) and it doesn't look like I can use my current approach anymore. Can anyone point me to some samples or posts on how to get the latest version of Ninject working with a WCF project.
My current approach:
I wrote a module:
public class NinjectDependencyResolver : NinjectModule
{
public override void Load()
{
// Declare bindings
}
}
I added the Factory Attribute to my .svc file
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"
I added a Global.asax to the WCF project
public class Global : NinjectWcfApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new NinjectDependencyResolver());
}
}
Now I can modify the default constructor in my service and use constructor injection.
Any pointers on how I could upgrade are appreciated.
Thanks
Add Ninject.Web.Common and derive from NinjectHttpApplication or use the App_Start file that comes with the NuGet package.
It seem i can't get this to work. I made a custom MembershipProvider and i want to inject a repository inside but the [Inject] property just doesnt work.
public class PyrosphereMembershipProvider : MembershipProvider
{
[Inject]
protected IDepositoireUtilisateur DepositoireUtilisateur { get; set; }
[Inject]
protected IDepositoireProfile DepositoireProfile { get; set; }
...
I think this is because this class are created way before the MVC application is running which cause the actual problem. I am getting more problem trying to use the membershipprovider than making my own system.
About my ninject configuration i am using the App_Start directory method. All my binding are correct ive looked so that nothing to do with my bindings.
Any help is appreciated!
The ASP.NET Providers aren't designed for proper dependency injection. There are only workarounds for them.
Either you have to setup a binding for them and resolve atleast one instance before using them. E.g. by injecting an instance into the Global.asax or you have to Inject an instance manually before the first use (kernel.Inject(...)). Again most likely in the global.asax application start method.
I am trying to figure how to create tests for my controllers that are consuming a WCF service (via a proxy class)
The proxy class is pretty much identical to the one listed in this post http://blog.weminuche.net/2008/08/test-post.html
Base Controller
public abstract class ServiceProxyController<TService> : Controller
where TService : class
{
private readonly ServiceProxy<TService> _proxyHelper;
protected ServiceProxyController(string endpoint)
{
_proxyHelper = new ServiceProxy<TService>(endpoint);
}
private Stuff GetStuff(int num)
{
Call((service) => {
service.DoSomeStuff(num)
});
................
}
...........
}
Controller Implementation
public class MyController : ServiceProxyController<IService>
{
public MyController() : base("ServiceBindingName")
{
}
}
I want to be able to inject a proxy helper(???) into my controller so as I can mock it and therefor test the controller
How about injecting the proxy helper to the constructor (notice the introduction of an abstraction):
private readonly IServiceProxy<TService> _proxyHelper;
protected ServiceProxyController(IServiceProxy<TService> proxyHelper)
{
_proxyHelper = proxyHelper;
}
and the controller:
public MyController(IServiceProxy<TService> proxyHelper)
: base(proxyHelper)
{
}
This way in your unit test when instantiating the controller you could inject a mocked instance of the IServiceProxy<TService> interface.
You will then need to configure your DI framework to insert the proper implementation into the controller constructor which will wrap the actual ChannelFactory.
I just asked a similar question. I am injecting the service using structure map. I am dynamically creating a proxy using channel factory.
Look at this example for using Channel factory.
creating WCF ChannelFactory<T>
My question for your reference.
Rhinomocks - Mocking delegates
Note- Actually it was Darin who posted the ServiceInvoker