14

In my asp.net mvc application I'm using Ninject as a DI framework.

My HttpAccountService is used by my controllers to get info from and to cookies. For this I need the HttpContext.Current in the HttpAccountService. As this is a dependency I injected it throught the constructor as such:

kernel.Bind<IAccountService>()
    .To<HttpAccountService>()
    .InRequestScope()
    .WithConstructorArgument("context", HttpContext.Current);

Sadly this always binds to the same context which makes that after the first request finishes this context becomes outdated.

How should I correctly inject my HttpContext?

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Boris Callens
  • 90,659
  • 85
  • 207
  • 305

1 Answers1

23

WithConstructorArgument has an overload that takes a Func<NinjectContext,T>, i.e., you can use:

... .WithConstructorArgument("context",ninjectContext=>HttpContext.Current);

which will call the provided 'callback' lambda within the request processing and obtain the correct value at that point in time [as opposed to you calling the other overload and supplying a constant value which gets computed at Bind<> time].

(If you're not trying to Mock the context, I assume you'll consider using it inline)

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • That syntax doesn't seem to compile. It compiles with x=>HttpContext.Current, but this doesn't achieve the expected result. Could it be because I get my ninjectkernel from a (static) factory? – Boris Callens Sep 01 '10 at 20:52
  • On further inspection it seems I now DO get the correct context, but my problem must lie somehwere else. Thx – Boris Callens Sep 01 '10 at 20:57
  • for the record: it was because a RedirectToRoute resets that requests cookies. – Boris Callens Sep 01 '10 at 21:42
  • @Ruben - Is this how I would inject the current user into my Kernal? i.e. Http.Context.User, I want this user injected into my domain service however I am finding it difficult... After the user loggs on I would want to inject him and access him in my service layer that does not reference the web, would this be possible? – Haroon Jun 23 '11 at 05:28
  • @Haroon: While it's possible, it may not always be a good idea. Stuff like the current user should not generally be come into play (though you can do it by using `Ninject.Parameters.Parameter` with `shouldInherit` set to `true` and then in your `Bind`ing picking up the value. A far better general approach is to have your components depend on an e.g. `IUserContext` and have that manage the retrieval of relevant information. Typically you wouldnt use any `System.Web` stuff in your services layer directly. I recommend reading @Mark Seemann's top answers around here and the haze will lift quickly! – Ruben Bartelink Jun 23 '11 at 08:03
  • @Ruben: thanks for your reply, I dont understand where I actually do the binding for this or how, I did have a read through some of Marks answers that helped a bit, is it possible to see my gist and comment? you can find it @ https://gist.github.com/1042173 – Haroon Jun 23 '11 at 08:54
  • @Ruben: Totally ignore what I said, I managed to get it to work! :P It feels like one of those moments where something has clicked lol... Anyway, is this binding ok: Container.Bind().To().InRequestScope(); I am updating my gist, if you could comment that would be wonderful! – Haroon Jun 23 '11 at 09:10