WebApi and Ninject singleton scope - asp.net-web-api

Im using this article to get ninject to work with Asp.Net WebApi
http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/
This breaks all scopes, like InSingletonScope
edit: Answer was in the comments
Ok, I mostly figured it out. The problem is that the NinjectResolver's
BeginScope method returns a new NinjectScope passing in
_kernel.BeginBlock() to the constructor. This re-associates the instances from the scope that was declared in their bindings to the
new activation block.
So, what was once scoped to the request is now scoped to the
activation block.
To work around this I changed NinjectResolver like this:
public IDependencyScope BeginScope() { return new
NinjectScope(_kernel); }
Then, to keep the NinjectScope from disposing of the kernel itself, I
commented out everything in the NinjectScope's Dispose block.
As far as I can tell, this should not have much impact. The built-in
cache-and-collect mechanism will work as it typically does, polling
the GC and disposing instances in the cache automatically.
I think the core of the problem here is that WebApi itself is trying
to do the job of per-request scope management, but Ninject already has
a way of doing that job. The two different scoping mechanisms don't
seem to live in harmony.

Related

NServiceBus/MVC injection - Autofac doesn't like IControllerFactory?

all. I am getting started with NServiceBus and have a pretty good handle on the basics thanks to Pluralsight and the internet. I have an stock MVC 4 project and I have setup dependency injection for my controllers (thanks to this blog post).
Here is how I have my bus setup in Global.asax:
_bus = Configure.With()
.DefaultBuilder()
.ForMVC()
.Log4Net()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.SendOnly();
I am assigning it to a local private variable because I need access to the bus in Global so I can do some stuff on Session_End. However, when I run, I get the following error:
The requested service 'System.Web.Mvc.IControllerFactory' has not been
registered. To avoid this exception, either register a component to
provide the service, check for service registration using
IsRegistered(), or use the ResolveOptional() method to resolve an
optional dependency.
According to my stack trace, the failure point is when Autofac tries to resolve the type. For the sake of sanity, I removed the private variable and used just the Configure statement, same thing. I also have Ninject wired up in this app because that is my IoC of choice. Thinking that it was interfering with Autofac in some way, I removed Ninject from the equation, still not working.
So my question is, what am I doing wrong? Am I missing something? This is my first time with NServiceBus, but from everything I've seen, this should just work. Any info would be super helpful. Thanks.
Have a look at our MVC4 sample (this is running against v4, the next major release):
https://github.com/NServiceBus/NServiceBus/tree/develop/Samples/Messaging.Msmq/MyWebClient
I found the solution from your code, John! Here was my issue. This is what I had in my Dependency Resolver Adapter:
public object GetService(Type serviceType)
{
_builder.Build(serviceType);
}
What I needed to do was what you did in your MVC4 example:
public object GetService(Type serviceType)
{
return (Configure.Instance.Configurer.HasComponent(serviceType)) ? _builder.Build(serviceType) : null;
}
Once I did that, it all sorted itself out. Thanks again for the help!

Use Container/DependencyResolver in other dll

I'm trying to get myself familiar with MVC3 and autofac but I've encountered small problem that I'm having trouble resolving.
I am using autofac integrated with MVC3 and all works well, pages are loading correctly, dependencies are being injected and that's cool. What's bugging me is how to use autofac's Container or MVC's DependencyResover in class library project.
I'm trying to create static class that will help me handle domain events. I simply want to be able to call the method with event parameter and everything should be handeled by this class. Here is code:
public static IContainer Container { get; set; }
public static void Raise<T>(T e) where T : IDomainEvent
{
foreach (var eventHandler in DomainEventManager.Container.Resolve<IEnumerable<EventHandlers.Handles<T>>>())
{
eventHandler.Handle(e);
}
}
As you can see it's pretty straightforward and everything would work great if it wasn't MVC approach. Some of my dependencies are registeres as InstancePerHttpRequest (NHibernate' session), while other are registered as InstancePerDependency or SingleInstance. Thus when I try to use container created in my UI project, I get exception that there is no httpRequest tag available.
How can i reuse the Container created in web project to get access to all of it's features, including InstancePerHttpRequest and httpRequest tag?
Or maybe there is other solution to my problem? I was thinking about using delegate function to obtain event handlers, but I cannot (can I?) create generic delegate that I would not need to initialize with concrete type at time of assignment.
Why I want to do this using static class is basically every entity and aggregate or service needs to be able to raise domain event. Injecting EventManager into every one of these would be troublesome and static class is exactly what would resolve all my problems.
If anyone could help me get my head around it I would be grateful.
Cheers, Pako
You shouldn't be referencing your container directly from your app code. This looks like the Service Locator anti-pattern. The correct action is to pass your objects the services they need to do their jobs, usually done through constructor parameters. BUT... if you are going to insist on depending on a global static, then at least model EventManager as a singleton, such that usage would look like:
EventManager.Current.Raise<SomeEvent>(someObject);
and then you can set EventManager.Current equal to a properly constructed instance when your app is initialized.

How to pass an HttpContext to a dependency initialization in MVC3 application

I am using Ninject in MVC3 application.
One of my resolvable dependencies makes use of HttpContext.Current.Server.MapPath("~/App_Data")
Back when I was initializing an IoC container in Global.asax (Application_Start), I was able to just define in my module configuration:
.WithConstructorArgument("basePath", HttpContext.Current.Server.MapPath("~/App_Data"));
Since my module was being initialized from the same thread as the Application, HttContext.Current wasn't null.
Then I had to move my Dependency Injection initialization to an PreAppStart method, using the WebActivator. Since the HttContext is not yet available in this scenario, I had to remove the parameter initialization of my dep.
I had worked around the problem by resoling the HttpContext inside my class instance at runtime. But it turns out it was possible only as long as the instance was being called from the Request Thread. As soon as I have moved the resolved instance call to a separate thread (not to be halting the Controllers' ActionResult generation), I arrived at the same problem - no longer able to get HttpContext. How can I resolve it in my scenario?
P.S. Just figured out I still can just call a method on my dependency from Global.asax Application start and feed the HttpContext from there. Nevertheless, let me know which is the best way to do it.
There should be a way in Ninject to register the dependency in a lazy way using a delegate. This way it will only resolve it when you access the dependency.
Here is how I do it using StructureMap:
For<HttpContextBase>().Use(c => new HttpContextWrapper(HttpContext.Current));
As far as accessing the HttpContext from a different thread, you can use the AsyncManager.Sync(d) method that takes a delegate and runs it in the ASP .NET worker process.

MVC3 Action Filter Using Database (EF 4.1 DBContext, Ninject)

I'm trying to setup an 'Authorization' Filter on an Action, creating my own ActionFilterAttribute where I do a database lookup to determine if a user has access to a certain resource.
On my class inheriting from ActionFilterAttribute, I have created an Injected(Ninject) property to hold the service that I am using for the database access. I have a parameterless constructor so that I can use this as an attribute on my actions. In the 'OnActionExecuting' Method, I am able to gain access to the Injected property (it's not null), but the base DBCotext that it is using is closed.
This working fine, up until the RTM of MVC3, where the Release Notes stated:
Breaking Changes:
In previous versions of ASP.NET MVC, action filters are create per
request except in a few cases. This
behavior was never a guaranteed
behavior but merely an implementation
detail and the contract for filters
was to consider them stateless. In
ASP.NET MVC 3, filters are cached more
aggressively. Therefore, any custom
action filters which improperly store
instance state might be broken.
The first time I use this filter, it works as expected, but if I refresh the page or another user access this filter, I get the error:
The operation cannot be completed
because the DbContext has been
disposed.
which is what I guess I should expect given the breaking changes notes.
My question is this, what would be the preferred/recommended way of accomplishing what I need to do? Should this be in an ActionFilterAttribute, or should this 'authorization' be done somewhere else?
I'd do authentication in Application_AuthenticateRequest and authorization in your attribute using Thread.CurrentPrincipal, but your method should work too. You just need to count with fact that DbContext will be different for each request but your attribute won't. Something like this should do the trick (I'm assuming you are using DependencyResolver):
public class MyMightyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var context = (DbContext)DependencyResolver.Current.GetService(typeof(DbContext))
// authenticate, authorize, whatever
base.OnActionExecuting(filterContext);
}
}
I have been battling with this for a while and finally solved my problem. So here is my solution in the hope it may help someone else.
The setup:
1. I have an MVC3 project, a custom action filter that accesses the db using EF5 via a business service.
2. I use Unity and unity.MVC to resolve my dependencies on a per request basis.
3. I use property injection into my custom Action filter, as it has a parameterless constructor.
The result.
Dependency injection works correctly for all the services used by actions, my EF DbContext is correctly disposed of at the end of each request.
The Problem
Although my property dependency is resolved in my custom action filter, it contains a stale instance of my DbContext (e.g. it seems to have been cached from the previous request)
As mentioned in previous posts, MVC3 is more aggressive with filter caching and the state of a filter cannot be relied on. So the suggestion was to resolve the dependency in the OnActionExecuting method. So I removed my injected property and did just that called resolve on my unity container. However I still got a stale version of the DbContext. Any changes in the DB were correctly queried in my main actions, but the custom action filter didn’t pick them up.
The solution.
Unity.MVC Manages per-request lifetime by using child containers and disposing these at the end of each request. By resolving my dependency’s in the action filter from my unity container I was resolving from the parent container which is not disposed of on each request.
So rather than
IoC.Instance.CurrentContainer.Resolve<IService>();
I used this to obtain an instance of the child container rather than parent.
var childContainer = HttpContext.Current.Items["perRequestContainer"] as IUnityContainer;
var service = childContainer.Resolve<IServcie>();
I'm sure there must be a clean way to achive the same result, so please add suggestions.
Ok slight refinement to allow my unit test to inject a mock of the service.
1. remove the dependency resolve from the the OnActionexecuting and add two constructors.
public MyCustomActionfilter() : this(((IUnityContainer)HttpContext.Current.Items["perRequestContainer"].Resolve<IService>())
and
public MyCustomActionfilter(IService service)
{
this.service = service;
}
Now the constructor resolves your service and stores it as a private readonly. This can now be consumed in your OnActionExecutng function. Unit tests can now call the second constructor and inject a mock.

ASP.NET MembershipProvider and StructureMap

I was using the default AspNetSqlMembershipProvider in my application. Authentication is performed via an AuthenticationService (since I'm also supporting other forms of membership like OpenID).
My AuthenticationService takes a MembershipProvider as a constructor parameter and I am injecting the dependency using StructureMap like so:
For<MembershipProvider>().Use(Membership.Provider);
This will use the MembershipProvider configured in web.config. All this works great.
However, now I have rolled my own MembershipProvider that makes use of a repository class. Since the MembershipProvider isn't exactly IoC friendly, I added the following code to the MembershipProvider.Initialize method:
_membershipRepository = ObjectFactory.GetInstance<IMembershipRepository>();
However, this raises an exception, like StructureMap hasn't been initialized (cannot get instance of IMembershipRepository). However, if I remove the code and put breakpoints at my MembershipProvider's initialize method and my StructureMap bootstrapper, it does appear that StructureMap is configured before the MembershipProvider is initialized.
My only workaround so far is to add the above code to each method in the MembershipProvider that needs the repository. This works fine, but I am curious as to why I can't get my instance in the Initialize method. Is the MembershipProvider performing some internal initialization that runs before any of my own application code does?
Thanks
Ben
Yes, the provider is initialized by the ASP.Net runtime when the AppDomain is spun up, far in advance of any execution of your code.
You will need to choose another point to do your composition, perhaps in Global.Application_???.

Resources