Injecting HttpContext in Ninject 2 - dependency-injection

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?

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)

Related

Dependency Injection: Is there any such thing as lazy parameter passing?

DISCLAIMER: This is a general question about Dependency Injection without having to do with any specific product/project/DI-Solution. This question in no way is asking to compare features between DI solutions.
I am using DI in ASP.NET MVC 5 Project using SimpleWebInjector. Everything works cool as can be, my controllers have ctors that have parameters which have values injected properly, those dependencies have their own ctors that are getting params injected fine.
Now here is the peculiar scenario: One of the dependencies have a ctor parameter that can only be injected with a value provided to all Actions of my controller. How can I accomplish that? Is that even possible with DI?
One of the dependencies have a ctor parameter that can only be injected with a value provided to all Actions of my controller.
If the value is provided to an action, that means that it is runtime data. Runtime data should not be injected in to the constructor of your components. This is an anti-pattern, as explained here. In short, the article can be summarizd as:
Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. My advice is to let runtime data flow through the method calls of constructed object graphs.
The article gives 2 general solutions:
pass runtime data through method calls of the API or
retrieve runtime data from specific abstractions that allow resolving runtime data.
See how Castle Windsor, my favorite DI container, provides what you need.
container.Register(
Component.For<IDBContext>().ImplementedBy<CustomDBContext>()
.DependsOn(Dependency.OnValue("connectionString", connectionString))
);

Declaring DbContext for an MVC controller

Looking at some of the MVC examples online, I've see that typically in a controller the DbContext variable is declared as a private member variable (i.e. global) and accessible to all the methods.
But, I recently came across an article on ASP.NET Identity, and noticed in the controller, the DbContext is declared within each method (that requires it).
Is there a security benefit to this approach? Perhaps limit the lifespan of the security object(s) for better overall security?!?!
If not, then I see the first approach being more efficient, where the database context is instantiated upon the controller loading.
Below is all I could find about DbContext, but nothing to really answer my question.
DbContext declaration - Framework 4.1 - MVC 3.0
MVC, DbContext and Multithreading
On every request, a new instance of the controller is constructed. Therefore, for all intents and purposes, it does not really matter whether the dbcontext is instantiated in the constructor vs encapsulated in any given method.
Aside from a style choice, reasons to declare and contain a dbcontext in a given method is that:
Methods that do not need it will not instantiate the context, eliminating the overhead (if there is any). This can also be accomplished using a lazy initialization pattern.
The context is disposed of immediately as soon as a method is done with it, rather than at the end of the request. Generally this should not be a concern though; usually if users are waiting around for longer than a few seconds you have a bigger problem.
Different methods use different contexts.
Among others, some reasons to declare a single context and instantiate it once:
You have only one place that instantiates a context rather than many. In a typical application, most pages will need some information from the database anyway.
Methods that call other methods will not each hold on to their own instance of a context object.
You can create a base controller class that by default creates a dbcontext object, allowing you to be DRY in all inherited controllers.
Answer from #Ic. is pretty good. I wanted to add that if you need to pass information from your Request into your DbContext constructor then you need to create the instance of your DbContext inside your action methods. The reason is the Request object will be null till the control enters your action method.
More information: I had a need to build connection string dynamically depending on the location of the user. I saved the location as a cookie that I accessed through Request object. I had a valid Request inside the action method but it was null inside the constructor or at the class level properties of the controller.

StructureMap and items cached by HttpContext when unit testing

We are using StructureMap to cache a a class by InstanceScope.HttpContext. When unit testing a controller that depends on this type, null reference exceptions are thrown from within StructureMap that seem to indicate that it is trying to access the static current HttpContext (and not the MVC wrappers).
How could we fully configure HttpContext.Current (having decompliled structuremap it seems the error comes from here) to have a valid context that would work correctly with structuremap?
This is a known bug
Just implement the fix and compile.
Have you tried / You could use:
containter.For<ICupCakeService>().HybridHttpOrThreadLocalScoped().Use<MyCupCakeService>();
... Which will use HttpContext storage if it exists, otherwise use ThreadLocal storage.
More: StructureMap - Scoping and Lifecycle Management

Is an instance of my controller constructor created every time I request a new page in MVC3

I have quite a few things in the constructor of my controller. Is it the case that every time I request a new page with MVC3 then the constructor executes?
A controller instance is required to serve each request. And to obtain this instance (obviously) the controller constructor is called on each request. This being said you should avoid doing many things in this constructor. There are cases for example where for some particular action on this controller you don't need all this initialization and despite this if you put it in the constructor, it will be executed. If the tasks you perform are simply instantiating some other dependencies that your controller needs, then you shouldn't worry about performance, you should worry about properly architecting your application as this job should be handled by a DI framework.
Another common gotcha is that inside the constructor you don't yet have access to the HttpContext and some properties such as Request, Response, ... might not be available in the controller constructor. They become available in the Initialize method.
All this to say that I recommend you avoid putting code (other than storing ctor argument dependencies into private variables for injecting things like services, repositories, ...) in your constructor.
The Controller base class includes the ControllerContext which is a per-request context for a controller which includes references to HttpContext for example.
Let that sink in a moment.
It's very easy to write a custom ControllerBuilder or use the new DependencyResolver to serve up a singleton controller using your favorite DI container. But what that means is your controller may hold onto state from a previous request.
In fact, one of the most common bugs when people use Castle Windsor (which uses Singleton by default I've been told) to create their controllers is they get weird behavior.
As others have pointed out, if your controller is doing a lot of work in the constructor, refactor that work into a dependency on your controller which gets passed in via your controller's contstructor. Let's call that dependency a "service".
That service can itself be a singleton (as long as it doesn't hold onto per-request state) and you can use the DependencyResolver combined with your DI container to instantiate your controllers.
It's up to the ControllerFactory to determine this; the controller factory serves up the controller instance. You could build in the ability to cache the controller, but: it would be better not to pass those references via the ctor of the controller. It would be better to cache each reference separately, and pass to the controller during construction, and let the controller get recreated everytime. If you cache the controller, it will cache other references potentially like HttpContext, which would be not the current request.
HTH.
Yes, M Jacob and this helps us making Data Access request for new DataContext in each request and it is very efficient. it is recommended to initialize a new DataContext (in your controller constructor) in each request rather than making persistent DataContext.
Internet is stateless and the server cannot really distinguish you from any other person out there (technically speaking, ignoring sessions and cookies). You are served the content and connection with you is ended. On your new request the things start from scratch. I agree with you that inability to keep an object alive is an overhead, but even bigger overhead would be if million users made a request with a different requests to the same object. Keeping million copies of the same object is next to impossible.
Regards,
Huske

Construtor/Setter Injection using IoC in HttpHandler, is it possible?

I've ran into a rather hairy problem. There is probably a simple solution to this but I can't find it!
I have a custom HttpHandler that I want to process a request, log certain info then enter the details in the database. I'm using NUnit and Castle Windsor.
So I have two interfaces; one for logging the other for data entry, which are constructor injected. I quickly found out that there is no way to call the constructor as the default parameterless constructor is always called instead.
So I thought I would use Setter injection and let Castle windsor sort it out. This actually works as when I use container.Resolve<CustomHttpHandler>(); I can check that the logger is not null. (In Application_Start in Global.asax.cs)
The problem is although Castle Windsor can create the instance the http application is not using it??? I think??
Basically the whole reason for doing it this way was to be able to test the logger and data repository code in isolation via mocking and unit testing.
Any ideas how I can go about solving this problem?
Thanks!
Not possible, at least not directly. IHttpHandler objects are instantiated by the ASP.NET runtime and it doesn't allow Windsor to get involved in its creation. You can either:
Pull dependencies, by using the container as a service locator.
Set up a base handler that creates, injects and delegates to your own handlers (see how Spring does it)
Use the container as a service locator for another service that handles the entire request (as saret explained)
What you could do is have the HttpHandler call out to another object that actually handles the request. so in your HttpHandler's ProcessRequest method you would do something like this:
public void ProcessRequest(HttpContext context)
{
var myHandlerObject = container.Resolve<HandlerObject>();
myHandlerObject.ProcessRequest(context or some state/info that is required)
}

Resources