Search code examples
c#asp.net-web-apiunity-container

Web Api OWIN Host with Unity


I'm trying to implement UNITY on my WebApi2 application. The problem is that I'm using an existing SqlConnection, depending on an identifier found in the URL of the resource. So I need the identifier provided in the request uri, to create my context with. Is it possible to get the {dbIdentifier} from the request URI, and parse it into the constructor of MyRepo?

The Request usi will look like: /api/{dbIdentifier}/{controller}/{id}

The structure looks like...

Request POST /api/myDbIdentifier/my/ + PAYLOAD data

Controller:
public class MyController : ApiController
{
    private readonly IRepo _repo;

    public MyController(IRepo repo)
    {
        _repo = repo;
    }
}

Repo:
public class MyRepo : IRepo
{
    private readonly MyContext _context;

    public  MyRepo(string dbIdentifier)
    {
        _context = new MyContext(GetConnection(dbIdentifier));
    }

    public void Insert(string s)
    {
        //Inserting string in context and save changes
    }

    private DbConnection(string id)
    {
        //psudo find connecion from pool, and return instance of DbConnection...
    }
}

public interface IRepo
{
    void Insert(string s);
}

Context:
public class MyContext : DbContext
{
    public MyContext(DbConnection exitingConnection) : base(existingConnection, true)
    { }
}

Btw, it's my first time playing around with WebApi and Unity, so please bear with my ignorance.

UPDATED Unity part of my code...

UnityResolver (taken from https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection):

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer Container;

    public UnityResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException(nameof(container), "Please provider an IUnityContainer.");
        }
        Container = container;
    }

    public void Dispose()
    {
        Container.Dispose();
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return Container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return Container.ResolveAll(serviceType);
        }
        catch (Exception)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        return new UnityResolver(Container.CreateChildContainer());
    }
}

Unity Register part in my startup:

public static void Register(HttpConfiguration config)
{
    // Configuring DI Container fo IoC (Invert of Control)
    var container = new UnityContainer();
    container.RegisterType<IRepo, MyRepo>(new HierarchicalLifetimeManager());
    config.DependencyResolver = new UnityResolver(container);
}

Solution

  • You can try the following:

    1. Create a DelegatingHandler where you can access HttpRequestMessage.RequestUri

    2. Extract dbIdentifier from Uri

    3. Wrap dbIdentifier with a class (e.g. DbIdentifier) and register it in Unity using HierarchicalLifetimeManager

    4. Remember to register handler in Owin:

      httpConfiguration.MessageHandlers.Add(new DbIdentifierHandler());

    You can look into this post to find some inspiration: How to pass Owin context to a Repo being injected into Api controller