HttpHandler Property Injection using Ninject returning null
Asked Answered
P

2

2

I have the following httphandler:

public class NewHandler : IHttpHandler
{
    [Inject]
    public IFile FileReader
    {
        get;
        set;
    }

    public NewHandler()
    {
    }

    public void ProcessRequest(System.Web.HttpContext context)
    {
        ....
        var something = SomeMethod(FileReader);
        ....
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

This is my Ninject Module in the Global.asax.

internal class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<IFile>().To<FileWrapper>().InSingletonScope();
    }
}

Every time the handler fires the FileReader is NULL. Am I missing something? Is this the correct way to do property injection using Ninject?

Thanks

Polemics answered 2/9, 2010 at 17:12 Comment(0)
C
3

This is the correct way to do property injection with Ninject, but it won't work. You are probably using something like NinjectMvcApplication class as a base class for you application, that handles dependency injection for controllers and everything controllers might use (services, repositories). But HttpHandlers are not instantiated by the ControllerFactory so nothing takes care of injecting stuff.

Maybe there's better way to do it, but i used service locator to resolve the dependency. See http://code.dortikum.net/2010/08/05/asp-net-mvc-di-with-common-service-locator-and-ninject/.

UPDATE:

Try something like this:

public class NewHandler : IHttpHandler
{
    private readonly IFile _fileReader;

    public NewHandler()
    {
        _fileReader = ServiceLocator.Current.GetInstance<IFile>();
    }

    public void ProcessRequest(System.Web.HttpContext context)
    {
        ....
        var something = SomeMethod(_fileReader);
        ....
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}
Calculate answered 2/9, 2010 at 17:41 Comment(3)
Thanks! I read the article, interesting. Just to try it out I modified my application accordingly but I still manage to get NULL in the FileReader property when the ProcessRequest fires.Polemics
Yes, that approach works. Still curious as to why httphandlers can't do property injections the same way a controller can. Probably something to do with the request pipeline. If anyone knows please let me know. Necros, thanks again!!Polemics
As I explained in my answer, the controller factory takes care of injecting into controllers. If you wanted to inject into HttpHandlers automatically, you'd have to take control of what is creating HttpHandlers - msdn.microsoft.com/en-us/library/ms227439%28v=VS.100%29.aspxCalculate
T
1

If you're using Ninject.Web.Common, you should have a NinjectWebCommon.cs in your app_start folder. That class instantiates a Bootstrapper class which contains a singleton instance of the Ninject kernel. That Ninject kernel is actually available everywhere in your app which means it's also available in HTTP factory classes.

Here's how you can continue to use Ninject in more or less the same way you're using controllers:

IHttpHandlerFactory is the composition root for IHttpHandler instances and as such you will need to create an implementation of this interface and add the necessary configuration elements to your web.config.

MyHandlerFactory.cs:

public class MyHandlerFactory : IHttpHandlerFactory
{
    public bool IsReusable => false;

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
       // the bootstrapper class uses the singleton pattern to share the Ninject Kernel across your web app's ApplicationDomain
       var kernel = new Bootstrapper().Kernel;

       // assuming you have only one IHttpHandler binding in your NinjectWebCommon.cs
       return kernel.Get<IHttpHandler>();
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
       // nothing to release
    }
}

Now, add the necessary config elements for your new handler factory...

Web.config:

  <system.web>
    <httpHandlers>
      <add verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" />
    </httpHandlers>
  </system.web>
  <system.webServer>
    <handlers>
      <add name="MyHandlerFactory" verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" preCondition="integratedMode" />
    </handlers>
  </system.webServer>

Finally, add a binding for your IHttpHandler implementation...

NinjectWebCommon.cs:

private static void RegisterServices(IKernel kernel)
{
    // other bindings you already have

    // the binding for your handler factory
    Bind<IHttpHandler>().To<NewHandler>();
}
Tinnitus answered 31/10, 2018 at 17:34 Comment(2)
I read with later versions of ninject web common you can just inherit from Ninject.Web.HttpHandlerBase and it's supposed to work. Try that first if you're reading this.Tinnitus
This worked for me! Only needs one line in the web.config though - the bit in system.webServerHooks

© 2022 - 2024 — McMap. All rights reserved.