marisks

digging through code

Setting Up RavenDB in EPiServer

| Comments

I am using RavenDB in EPiServer for several months already. It is great replacement for DDS (Dynamic Data Store).

Setting up RavenDB in EPiServer is same as in some other ASP.NET application. I am using StructureMap as dependency resolver, but it could be any DI container. I created StructureMap Registry and I am registering there DocumentStore as singleton and DocumentSession as HybridHttpOrThreadLocalScoped:

public class RavenDbRegistry : Registry
{
    public RavenDbRegistry()
    {
        For<IDocumentStore>()
                .Singleton()
                .Use(
                     context =>
                     new DocumentStore
                         {
                                 ConnectionStringName = "RavenDB"
                         }.Initialize()
                );

        For<IDocumentSession>()
                .HybridHttpOrThreadLocalScoped()
                .Use(
                     context =>
                     context
                             .GetInstance<IDocumentStore>()
                             .OpenSession());
    }
}

Connection string is retrieved same as in SQL server - from connectionStrings section in Web.config and looks like this: “Url=http://localhost:8080;Database=Stores”

After creating Registry do not forget to add it and other Registries to container:

public class StructureMapBootStrapper
{
    public static IContainer Configure()
    {
        ObjectFactory.Initialize(
                                 x =>
                                 {
                                     x.AddRegistry<RepositoryRegistry>();
                                     x.AddRegistry<ServiceRegistry>();
                                     x.AddRegistry<RavenDbRegistry>();
                                 });

        return ObjectFactory.Container;
    }
}

Initialize container in Global.asax on Application_Start.

protected void Application_Start(object sender, EventArgs e)
{
    var container = StructureMapBootStrapper.Configure();
    // Other initialization code ...
}

If you have setup your composition root properly (see previous articles about Web API here and here), you can use IDocumentSession in your code by injecting it. For example, using it in Web API:

public class StoreController : ApiController
{
    IDocumentSession session;
    public StoreController(IDocumentSession session)
    {
        this.session = session;
    }

    public  Store Get(string id)
    {
        return session.Load<Store>(id);
    }
}

Disposables, StructureMap and Web API Composition Root

| Comments

In the last article I wrote how to create StructureMap composition root for Web API, but I mentioned that it will not work with dependences which are disposable. Solution for this issue is simple - use StructureMap’s nested containers.

To implement it you have to change Create method of the class which implements IHttpControllerActivator. Create nested container first, register it for dispose on HttpRequestMessage and then resolve Web API controller using nested container. When nested container gets disposed it will call Dispose method on each disposable instance which it created.

Here is the code:

public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
{
    var nestedContainer = container.GetNestedContainer();
    request.RegisterForDispose(nestedContainer);
    return (IHttpController)nestedContainer.GetInstance(controllerType);
}

And do not to forget replace default IHttpControlelrActivator with new one.

GlobalConfiguration.Configuration.Services
        .Replace(typeof(IHttpControllerActivator),
            new StructureMapHttpControllerActivator(container));

Better Way to Configure StructureMap in ASP.NET WebAPI

| Comments

Few months ago Mark Seeman posted article about why using Web API’s IDependencyResolver is not appropriate. He suggests composing the dependency graph in IHttpControllerActivator because it provides context for composition. More about it could be read in his article.

In other article Mark shows how to set up Castle Windsor container for Web API. I am going to show implementation for StructureMap. All you need to do is create custom IHttpControllerActivator implementation and implement Create method where you resolve controller instances. As controller types are concrete classes we just have to call GetInstance method by providing controller type.

public class StructureMapHttpControllerActivator : IHttpControllerActivator
{
    private readonly IContainer container;

    public StructureMapHttpControllerActivator(IContainer container)
    {
        this.container = container;
    }

    public IHttpController Create(
            HttpRequestMessage request,
            HttpControllerDescriptor controllerDescriptor,
            Type controllerType)
    {
        return (IHttpController)this.container.GetInstance(controllerType);
    }
}

It will resolve any dependencies required by controller on controller creation.

But this solution will do well only if you do not have any disposable dependencies. With StructureMap you have to release any disposable dependences manually.

To register new IHttpControllerActivator just replace default one with yours in Global.asax on application start.

GlobalConfiguration.Configuration.Services
    .Replace(typeof(IHttpControllerActivator), 
        new StructureMapHttpControllerActivator(container));

Configuring StructureMap in ASP.NET WebAPI

| Comments

Last week I started to work in project with WebAPI and first thing what I noticed was improper usage of StructureMap as IoC container. I googled for StrutureMap configuration in WebAPI, but couldn’t find good solution. But, I found great tutorial how to inject dependencies into WebAPI controllers and do dependency injection with Unity IoC container: Using the Web API Dependency Resolver.

Dependency injection in WebAPI are done with two classes - first implements IDependencyScope interface and second inherits first class and implements IDependencyResolver interface. IDependencyScope represents child scope - any resources created in it should be released in Dispose method. Unity container supports creating child containers and it is used in WebAPI. StructureMap starting with version 2.6.1 also supports child container creation - those are called “nested containers” (“Nested Containers” in StructureMap 2.6.1). When nested containers in StructureMap are disposed, all transient objects that it created also are disposed - that’s what we want to achieve in IDependencyScope implementation. Solution is easy - just replace Unity implementation from Using the Web API Dependency Resolver article with StructureMap implementation.

Here is final result:

public class StructureMapScope : IDependencyScope
{
    private readonly IContainer container;

    public StructureMapScope(IContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType == null)
        {
            return null;
        }

        if (serviceType.IsAbstract || serviceType.IsInterface)
        {
            return this.container.TryGetInstance(serviceType);
        }

        return this.container.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.container.GetAllInstances(serviceType).Cast<object>();
    }

    public void Dispose()
    {
        this.container.Dispose();
    }
}

public class StructureMapDependencyResolver : StructureMapScope, IDependencyResolver
{
    private readonly IContainer container;

    public StructureMapDependencyResolver(IContainer container) : base(container)
    {
        this.container = container;
    }

    public IDependencyScope BeginScope()
    {
        var childContainer = this.container.GetNestedContainer();
        return new StructureMapScope(childContainer);
    }
}

Finally you have to initialize your container and register your dependency resolver in Global.asax:

// Initialize your container here ...
GobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);