Skip to content

Instantly share code, notes, and snippets.

@hyrmn
Created April 1, 2014 20:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyrmn/9922449 to your computer and use it in GitHub Desktop.
Save hyrmn/9922449 to your computer and use it in GitHub Desktop.
//This is for your web api controllers.
public class HttpControllerActivator : IHttpControllerActivator
{
private readonly IContainer _container;
public HttpControllerActivator(IContainer container)
{
_container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var nestedContainer = _container.GetNestedContainer();
nestedContainer.Inject(typeof(HttpRequestMessage), request);
nestedContainer.Inject(RequestKeys.BusinessKey, request.BusinessId());
request.RegisterForDispose(nestedContainer);
return (IHttpController)nestedContainer.GetInstance(controllerType);
}
}
public static class IoC
{
public static IContainer Initialize()
{
//... do the IOC type things in here.
}
}
//This is for asp.net mvc controllers. Based on Stig Christensen's example at
// https://groups.google.com/forum/#!topic/structuremap-users/ELY2g0dwUIo
public class MvcControllerFactory : DefaultControllerFactory
{
private const string NestedContainerKey = "NestedContainer";
private readonly IContainer _container;
public MvcControllerFactory(IContainer container)
{
_container = container;
}
public static void DisposeNestedContainer()
{
var nestedContainer = HttpContext.Current.Items[NestedContainerKey] as IContainer;
if (nestedContainer != null)
{
nestedContainer.Dispose();
}
}
private IContainer CreateOrGetNestedContainer()
{
var nestedContainer = HttpContext.Current.Items[NestedContainerKey] as IContainer;
if (nestedContainer == null)
{
nestedContainer = _container.GetNestedContainer();
HttpContext.Current.Items[NestedContainerKey] = nestedContainer;
}
return nestedContainer;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return CreateOrGetNestedContainer().GetInstance(controllerType) as Controller;
}
}
[assembly: PreApplicationStartMethod(typeof(StructuremapMvc), "Start")]
namespace TheThing.Web.App_Start
{
public static class StructuremapMvc
{
public static void Start()
{
var container = IoC.Initialize();
ControllerBuilder.Current.SetControllerFactory(new MvcControllerFactory(container));
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new HttpControllerActivator(container));
}
}
}
//in your global asax, you'll want to ensure you're disposing of your nested container at the end of the request.
//Note, this is for mvc controllers only. The web api http controller resolver registers itself for disposal.
public class MvcApplication : HttpApplication
{
protected void Application_EndRequest(object sender, EventArgs e)
{
MvcControllerFactory.DisposeNestedContainer();
}
}
@hyrmn
Copy link
Author

hyrmn commented Apr 1, 2014

I don't have a use case that requires DependencyResolver and the MvcControllerFactory. Are you using that for resolving attribute dependencies?

@hyrmn
Copy link
Author

hyrmn commented Apr 1, 2014

@khalidabuhakmeh Want to spin up a small repo with an example filter? Or, I could.

I was using a similar approach.

My Sm web activator used to look like:

[assembly: PreApplicationStartMethod(typeof(StructuremapMvc), "Start")]

namespace TheThing.Web.App_Start
{
    public static class StructuremapMvc
    {
        public static void Start()
        {
            var container = IoC.Initialize();

            DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
            GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new HttpControllerActivator(container));
        }
    }
}

However, the details behind the SM resolver I was using are a bit more involved. I believe it was the StructureMap.MVC4 nuget package (code-only package so worth looking at)

I suspect it'd be fine to set both the dependency resolver and a controller activator. However, we'd want to see if we can notice any weird behavior where it's creating a separate child container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment